1 条题解

  • 0
    @ 2025-8-24 22:39:58

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar 离散小波变换°
    有志不在年高,无志空长百岁

    搬运于2025-08-24 22:39:58,当前版本为作者最后更新于2022-08-30 11:19:15,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    upd 2022.9.11\text{upd 2022.9.11}:原来有几句神志不清写错了,现在已经修正。

    题解

    注意到这样一个性质:每次操作选择的值(假设为 ci=ai+bivc_i=a_i+b_iv,其中 bib_i 是之前选中这个位置的次数)肯定会构成一些公差为 vv 的等差数列,且对于相邻的两个等差数列,后一个等差数列的第一项减去前一个等差数列的最后一项 >v>v

    这个性质可以这样理解:在第 ii 次操作选择了位置 jj 之后,相当于是给 jj 的价值加上了 vv,而对于第 i+1i + 1 次操作,因为第 ii 次操作选了位置 jj,所以 aj+bj×va_j + b_j \times v[1,i][1,i] 中最大的,现在 bjbj+1b_j \leftarrow b_j + 1aj+bj×va_j + b_j \times v 一定也还是 [1,i][1,i] 中最大的,所以第 ii 次操作要么选第 i1i - 1 次操作选的位置,要么选第 ii 个位置。

    而选择第 ii 个位置的充分条件就是第 ii 个位置不劣,即 cici1+vc_i \ge c_{i - 1} + v

    若第 ii 个位置劣于 i1i - 1 次操作选择的位置,则第 ii 次操作还是选择第 i1i - 1 次操作选择的位置,ci=ci1+vc_i = c_{i - 1} + v

    由这个性质,可以发现选择第 xx 个位置的操作一定是在一个连续子区间 [x,y][x,y] 中。

    O(nlogn)\mathcal O(n\log n) 做法

    现在把一段等差数列压成一段一起维护,记录每一段的首项位置。

    然后用一个指针 ii 从右向左扫,每次维护的是当只考虑 [i,n][i,n] 时,[i,n][i,n] 每一个位置对应的 cic_i 构成的那些等差数列。

    先讲一下这个东西怎么维护:每次从 i+1i + 1 的结果推导出 ii 的结果,那么后面的一些段可能会转而选择 ii,即 aia_i 较优,显然可以发现两点:

    1. 如果一个等差数列的首项选择了 ii,那么这个等差数列会全部选择 ii
    2. 一定是一些连续的等差数列选择 ii

    每次我们可以暴力去删除选择 ii 的段,然后加入一个新的等差数列,这个是均摊 O(1)O(1) 的。每次查询的时候,找到 [x+1,n][x + 1,n] 对应的信息,这样就成功撤销掉了 xx 的影响。

    然后在这些等差数列段上面二分,找到最少选择几个段才能使有 k1 k - 1 次操作选择 xx,然后通过数学方法计算出,axa_x 最小修改为多少,可以使得最后一个必须选择 xx 的段选择 xx

    不过这样我们没有考虑 [1,x1][1,x - 1] 的影响,所以我们还要将答案与需要使 xx 选择 xx 的答案取 max\max

    O(n)\mathcal O(n) 做法

    考虑第 ii 次操作。啥时候我们要选择 j  (j<i)j\;(j<i) 位置而不选择 ii 位置呢?那应该是 aj+v(ij)aia_j+v(i-j)\ge a_i。移项,发现 ajvjaivia_j-vj\ge a_i-vi

    根据刚刚的结论,选择位置 ii 的操作一定是一段连续的区间 [i,i+t][i,i+t]。现在我们希望选择位置 xx 的操作要至少 kk 个。那需要满足两个要求:

    • xx 次操作选择了 xx 位置。
    • yy 次操作选择了 xx 位置,其中 y=x,x+1,,x+k1y=x,x+1,\cdots,x+k-1

    wi=aiviw_i=a_i-vi,那么这两个要求相当于:

    • wxmaxy<x{wy}w_x\ge\max_{y<x} \{w_y\}。注意这是大于等于,因为 ww 值相同时会选择最靠后的那个。
    • wx>maxx<yx+k1{wy}w_x> \max_{x<y\le x+k-1} \{w_y\}。这里是严格大于,原因同上。

    si=maxji{wj}s_i=\max_{j\le i} \{w_j\},容易发现第一个操作就相当于 wxsxw_x\ge s_x。问题在于第二个操作。如果 sx+k1s_{x+k-1} 第一次取得最大值时,选取的就是 wxw_x,那无法通过 wx+k1w_{x+k-1} 得到结果。但是若 sx+k1s_{x+k-1} 第一次取最大值时不是由于 wxw_x,那就可以直接选取。

    为什么呢?此时 wxw_x 的值,就等于:

    $$\max_{y\le x+k-1,y\neq x}\{w_y\}=\max\{\max_{y<x}\{w_y\},\max_{x<y\le x+k-1} \{w_y\}\} $$

    现在处理 sx+k1s_{x+k-1} 取最大时选取的就是 wxw_x 的情况。考虑前缀非严格次大值 sx+k1s'_{x+k-1},那么它就相当于从 xx 以外的位置选取最大值了。

    参考代码

    #include<bits/stdc++.h>
    #define up(l,r,i) for(int i=l;i<=r;i++)
    #define dn(l,r,i) for(int i=l;i>=r;i--)
    using namespace std;
    typedef long long i64;
    const int INF =2147483647;
    const int MAXN =1e7+3;
    int n,m,v,w,l,F[MAXN],G[MAXN],A[MAXN],X[MAXN],K[MAXN];
    i64 ans1,ans2; char _file[256];
    int qread(){
    	int w=1,c,ret;
    	while((c=getchar())> '9'||c< '0') w=(c=='-'?-1:1); ret=c-'0';
    	while((c=getchar())>='0'&&c<='9') ret=ret*10+c-'0';
    	return ret*w;
    }
    int main(int argc,char **argv){
    	n=qread(),m=qread(),v=qread();
    	up(1,n,i) A[i]=qread();
    	up(1,m,i) X[i]=qread(),K[i]=qread();	
        A[0]=-INF;
    	up(1,n,i){
    		A[i]=w=A[i]-i*v;
    		if(w>=A[F[i-1]]) G[i]=F[i-1],F[i]=i; else
    		if(w>=A[G[i-1]]) G[i]=i,F[i]=F[i-1]; else
    		G[i]=G[i-1],F[i]=F[i-1];
    	}
    	up(1,m,i){
    		int x=X[i],k=K[i],y=x+k-1; l=0;
    		if(y<n) l=max(0,x*v+(F[y]==x?A[G[y]]+(G[y]>x):A[F[y]]+(F[y]>x)));
            ans1^=l,ans2+=l;
    	}
        printf("%lld %lld\n",ans1,ans2);
    	return 0;
    }
    
    • 1

    信息

    ID
    5837
    时间
    2000ms
    内存
    128MiB
    难度
    4
    标签
    递交数
    0
    已通过
    0
    上传者