1 sequence
给出n个二元对(ai, bi),从中确定最长不下降子串,其中位置i的值可以为ai到bi的任意一个。(通俗的讲就是,每个位置都可定一个值,介于ai与bi之间,再找出这个串的最长不下降子串)。 n<=10^6
<GREEDY>
这道题首先可以用贪心求解,从每个位置推下去就可以了。 fi= max(f i-1, a[i]) {fi-1 <= b[i]}
<ADVANCED>
我用的是维护一个指针p,顺序枚举i, 从位置p到位置i这串是可行的, 并且维护f数组。若枚举到了一个j,发现 fj-1> bj , 我们可以调整i,使得fj-1下降, 再看看是否可行。
所以我们记录一个d数组, di= fi- ai。
那我们很直观的是使 p = Pos of Min( Dx) +1 {p<=x<j},这样可以使得fj-1下降 r , r= Min (Dy) {p‘<=y<j} p'是新的p
通俗一点讲呢, d数组是每个数的f值还可以下降多少, 那么 Min(Dx){p<=x<j} 就是整串 p~j-1都可下降的数目(因为这是不下降子序列,下降必须整串下降)。
下降完了之后, 那么Min(Dx)这个位置呢,就卡住了这个序列(变成了0)。
若现在下降了的fj-1还大于bj, 那么我就要把p调整到 这个位置 之后, 这样后面的fj-1才可以继续下降。
所以现在的操作成了
1. 下降
2. 判断 fj-1 与 bj 的大小关系, 若bj大, 那么 跳出, 否则继续
3. 调整位置p,若无位置可转了,那么跳出。
4. 转1
所以总体实现两个操作: 1 找出当前序列的最小值 2把某个位置之前的数全部删除
所以用单调队列实现。
2 connon
给出不上升的数列(N个数)hi,和M种操作,每种操作可以使不大于ai的数减去di(减去以后小于0的视为0), 为k次操作,可以使多少数变为0,并求此情况下剩余几次操作。
N<=250000, m<=500, di<=500, ai与数列中的数均小于10^18.
首先给出最直接的做法。
消除每一个数都有一个总次数, 而且若A>B, 那么B的消除次数不比A的大。
那么我们做一次Dp, Fi为消除i这个数需要多少次。 Fi = Fi-x +1 {x为所有操作中 ai大于等于i 的中 最大 的di}
时间复杂度O(mlogm + max(hi)).
正解只是加了一点东西。首先我们把无用的操作去除掉之后共组成了S个区间, 每个区间的x值是确定的(x为Dp方程中)。
对于Fp, 若属于R区间, 那么 Fp= Fp-k*x + k {p-k*x<= R-1区间的ai值}, 看做进行了k次操作。
注意di<=500, 所以 p-k*x 与 a[R-1]必定差小于500.
所以对于每个区间预处理500个f值就可以了。