1、前言
今天是选拔考试第三天,所谓的省队难度,确实有点难,但是我们的发挥比实际难度还要差,暴力100分全场本年级的没有一个拿到,还有一大堆爆0的。好吧。cyb大神(@Delayyy)出的题,和他交流了一下,确实他看了成绩心情也是复杂的。三道题的话都是他国家集训队的作业题,CodeForces上面有英文原题,这下好了。这次考试不刻意作正解分析,更偏向于总结。
2、Tree 种树
大概题意:
在一个数列中种树,每过一个月树长高1m。每个月初,你会收到两种要求之一:在位置p种一棵高度为h的树;砍掉当前第x棵树,且保证以后不会再种。每次操作之后求其最长上升子序列。
总结:
这道题还是成功地把暴力打对了,直接模拟种树,砍树,用O(n log n)暴力求出最长上升子序列。考场上中间存在全部为种树操作的20分,但是n<=10^5,于是无聊写了个贪心自以为能够捞分,后来看了题解就打消了念头 = =。
题解(from Delayyy):
把每棵树看做二维平面上的一个点(pos[i],h[i]),那么最长上升子序列等价于:每个点只能走到自己右上方的点,走的最长的链。
定义f[i]表示从点i出发走的最长的链。我们发现,砍的树一定是最左边的10棵之一,种的树一定是最下的10棵之一。那么每次操作,我们删除对应的10个节点,然后按次序再逐个加入平面。每加入一个点,我们就要重新计算他的f值。
由于加入时一定x或y有序,所以只要查询另一个坐标的前缀f最大值。于是我们对x轴、y轴分别开一棵线段树来维护f值,这样每次加入一个点时,用O(log w)可以查询并计算出他的f值,再用O(log w)就能更新线段树。(w表示坐标范围)
// 自己慢慢看吧。。。
3、Matrix 数字矩阵
大概题意:
有一个形如这样的数字矩阵:
1 2 5 10 17 26
4 3 6 11 18 27
9 8 7 12 19 28
16 15 14 13 20 29
25 24 23 22 21 30
36 35 34 33 32 31
有t组询问,每次给定x1,y1,x2,y2,你需要计算这个子矩阵之和的后10位,特别地,如果超过10位,需要在数字前加上“...”。
总结:
这道题的暴力完全打错了。。。确实是太单纯了恩。注意,首先可以确定的是,对于某一个矩阵,要拆分成几个部分进行前缀矩阵的计算,但是在这个过程中,倘若你发现其数值大于10^10了就加上“...”,显然是不成立的,因为大于10^10的部分可能根本不在你所求矩阵之内(慢慢思考一下)。
同样还有一个问题需要考虑,若取余之后的数值<=10^9,要在“...”之后补充若干个0。具体做法参见题解中的分析,总而言之的话,做题不要太过于想当然吧。
题解(from Delayyy):
保留后10位等价于对10^10取模,然而这样是不够的,我们并不知道答案是否超过10位。解决方案是,再在mod 10^10+9的意义下做一次,可以大致认为答案不超过10^10当且仅当两次算出的答案一样。
令f[x][y]=a[i][j](1<=i<=x,1<=j<=y),对于每一组询问,转化为:
f[x2,y2]-f[x1-1][y2]-f[x2,y1-1]+f[x1-1][y1-1]。
首先我们可以发现,对于f[x][y],当x=y时,可以直接O(1)算出(等差数列和公式)。然后,当x!=y时,就存在一部分不属于直接计算部分,对面多出来的x行,每一行都是连续的若干数字(列也是同理),求出第一行的和S[1],给答案加上x*S[1],这样每一行剩下没计算的值形如:
1 1
2 2*t+2
3 3*t+2+4
4 4*t+2+4+6
求和起来为:t*i+2*i*(x-i-1) (1<=i<=x)
这个式子拆开就是一些i(1<=i<=n)和 i^2(1<=i<=n)和一些常数,都是可以O(1)求的。好吧由于mod有点大,要用O(log)的大数乘法,但是其实有一种O(1)的写法,省略。
4、Happy 愉悦
大概题意:
有一个数列a[1..n],每次你可以删除a[l..r],满足:|a[i]-a[i+1]|=1 (l<=i<r);2a[i]-a[i+1]-a[i-1]>=0(l<i<r)。删除长为x的连续一段可以获得val[x]的收益,求最大收益。
总结:
大概题意里没有提到,其实原题里面有一句很重要的话——每次删除之后两端的序列会重新连接起来!!!考试的时候看到了,但是由于最后时间比较紧,所以导致写DFS的时候没有去接啊。。。结果捧着个10分回来了。以后要多加注意细节啊。