1 条题解

  • 0
    @ 2025-8-24 22:04:37

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar wangif424
    想赢就会输,想输就能输|天不予而不取,不受其咎也欤?|分离四级动力组|常长老|与原生质层分离中|被离散化|生活,还有尸体和警方|登高而望,不如跂而博见矣

    搬运于2025-08-24 22:04:37,当前版本为作者最后更新于2024-02-27 18:19:43,作者可能在搬运后再次修改,您可在原文处查看最新版

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

    以下是正文


    P4855题解

    思路

    这道题乍一看非常不可做,要实现区间加一个数,区间加等差数列和区间第 kk 小。

    不过手玩样例后可以发现每次查询中对 aa 产生的变化仅在当次查询中生效。

    而且因为 zzzz 给定,所以对于所有查询中 iji\le j 的部分变化后的量都相同,于是可以维护一个数组 aizza_i-zz

    因此,不难想到分两部分处理。

    再思考 i>ji\gt j 的部分如何处理,尝试找通性,ai+ij1a_i+i-j_1ai+ij2a_i+i-j_2 中,仅有每次的 jj 不同,但在单个询问中固定,于是可以再维护一个数组 ai+ia_i+i

    做法

    由于要区间第 kk 小,且题面中未明确值域,所以使用主席树解决此题。

    用两棵主席树分别维护 aizza_i-zzai+ia_i+i

    对于每次查询,由于不便于(或者我太蒟)直接查询第 kk 小,于是改为二分查找。

    二分一个最小在当前的 aa 中小于等于自己的数的个数大于等于 kk 的数就是答案。

    小于等于 xx 的数的个数可以分两部分求,为 xxaizz,ija_i-zz,i\le j 中的最大排名,和 x+jx+jai+i,i>ja_i+i,i\gt j 中的最大排名的和。

    AC代码

    #include<bits/stdc++.h>
    #define R(x) x=read()
    using namespace std;
    char pbuf[1<<20], *pp=pbuf;
    void swap(int &a,int &b){a^=b^=a^=b;}
    inline void push(const char &c){if(pp - pbuf == 1<<20)fwrite(pbuf, 1, 1<<20, stdout),pp = pbuf;*pp++ = c;}
    class io{public:~io(){fwrite(pbuf, 1, pp - pbuf, stdout);}}_;
    inline void write(int x) {
        if (x<0)x=-x,push('-');
        int sta[35],top=0;
        do{sta[top++]=x%10,x/=10;}while (x);
        while(top)push(sta[--top]^'0');
    }
    #ifndef LOCAL
        char buf[1<<23],*p1=buf,*p2=buf,obuf[1<<23],*O=obuf;
        #define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
    #endif
    inline int read() {
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
        while(isdigit(ch)) x=x*10+(ch^48),ch=getchar();
        return x*f;
    }
    int n,q,zz;
    #define N 60010
    int a[N];
    struct node{
        int ls,rs,s;
    }t[N<<6];
    int siz;
    int rt[N],r2[N];
    void update(int u,int v,int l,int r,int pos){
        t[v].s=t[u].s+1;
        if(l==r)return;
        int mid=(l+r)>>1;
        if(!t[u].ls)t[u].ls=++siz;
        if(!t[u].ls)t[u].rs=++siz;
        t[v].ls=t[u].ls;
        t[v].rs=t[u].rs;
        if(pos<=mid){
            t[v].ls=++siz;
            update(t[u].ls,t[v].ls,l,mid,pos);
        }
        else{
            t[v].rs=++siz;
            update(t[u].rs,t[v].rs,mid+1,r,pos);
        }
    }
    int query(int u,int v,int l,int r,int x){
        if(l==r)return t[v].s-t[u].s;
        int mid=(l+r)>>1;
        if(x<=mid)return query(t[u].ls,t[v].ls,l,mid,x);
        else return t[t[v].ls].s-t[t[u].ls].s+query(t[u].rs,t[v].rs,mid+1,r,x);
    }
    int ls;
    signed main(){
        R(n);R(q);R(zz);
        for(int i=1;i<=n;i++)R(a[i]);
        rt[0]=++siz;
        r2[0]=++siz;
        for(int i=1;i<=n;i++){
            rt[i]=++siz;
            r2[i]=++siz;
            update(rt[i-1],rt[i],-1e9,1e9,a[i]-zz);
            update(r2[i-1],r2[i],-1e9,1e9,a[i]+i);
        }
        while(q--){
            int R(j),R(k);
            j=(j^ls)%n+1;
            k=(k^ls)%n+1;
            int l=-1e9,r=1e9;
            while(l<r){
                int mid=(l+r)>>1;
                if(query(rt[0],rt[j],-1e9,1e9,mid)+query(r2[j],r2[n],-1e9,1e9,mid+j)>=k)r=mid;
                else l=mid+1;
            }
            // for(int i=1;i<=n;i++){
            //     if(i<=j)write(a[i]-zz);
            //     else write(a[i]-j+i);
            //     push(' ');
            // }
            // push('\n');
            // int x=11932;
            // write(query(rt[0],rt[j],-1e9,1e9,x));write(query(r2[j],r2[n],-1e9,1e9,x+j));push('\n');
            // write(j);push(' ');
            // write(k);push('|');
            write(l);
            // push(' ');
            // write(query(rt[0],rt[j],-1e9,1e9,l));write(query(r2[j],r2[n],-1e9,1e9,l+j));
            push('\n');
            ls=l>0?l:-l;
        }
        return 0;
    }
    
    • 1

    信息

    ID
    2931
    时间
    2000ms
    内存
    500MiB
    难度
    6
    标签
    (无)
    递交数
    0
    已通过
    0
    上传者