bzoj3065带插入区间K小值

来源:互联网 发布:新手入门编程语言 编辑:程序博客网 时间:2024/05/21 14:02

这题其实好像很难,但是听werkeytom_ftd说可以用块链水,于是就很开心地去打了个块状链表套主席树,插入操作就直接插到一个块中,注意如果块的大小2*block就将块分开,注意每一个修改或插入都要修改后继的状态,贴代码:

#include<iostream>#include<algorithm>#include<cstdio>#include<cmath>#include<cstring>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fd(i,a,b) for(int i=a;i>=b;i--)using namespace std;const int N = 35010;const int M = 610;const int lim = 70000;int root[M][M],s[M],a[M][M],next[M],m;struct point{    int l,r,tot,p;}tree[M*M*2*18];int tot;int n,q,block,lastans,dep,u1,v1,u2,v2;int rt[M];int tt[M*M*2*18],head,tail;void find(int x,int &u1,int &v1){    int ss=0,last=0;    for(int i=1;i;i=next[i]){        if (ss+s[i]>=x||next[i]==0){            u1=i;            v1=x-ss;            break;        }        ss+=s[i];    }}void prepare(){    fo(i,1,tot)tt[i]=i;    head=tail=0;}int getp(){    head=head%tot+1;    return tt[head];}void putp(int x){    tail=tail%tot+1;    tt[tail]=x;}void clear(int x){    if (!x)return;    putp(x);    clear(tree[x].p);}void inse(int l,int r,int qf,int &now,int x,int v){    tree[now=getp()]=tree[qf];    tree[now].tot+=v;    if (l==r)return;    int mid=(l+r)/2;    if (x<=mid){        inse(l,mid,tree[qf].l,tree[now].l,x,v);        tree[now].p=tree[now].l;    }    else{        inse(mid+1,r,tree[qf].r,tree[now].r,x,v);        tree[now].p=tree[now].r;    }}int getans(int l,int r,int k){    if (l==r)return l;    int mid=(l+r)/2,ss=0;    if (u1!=u2){        fo(i,v1,s[u1])if (l<=a[u1][i]&&a[u1][i]<=mid)ss++;        fo(i,1,v2)if (l<=a[u2][i]&&a[u2][i]<=mid)ss++;        if (next[u1]!=u2)        for(int i=next[u1];i!=u2;i=next[i])            ss+=tree[tree[rt[i]].l].tot;    }    else fo(i,v1,v2)if (l<=a[u1][i]&&a[u1][i]<=mid)ss++;    if (ss>=k){        for(int i=u1;i!=u2;i=next[i])            rt[i]=tree[rt[i]].l;        return getans(l,mid,k);    }    else{        for(int i=u1;i!=u2;i=next[i])            rt[i]=tree[rt[i]].r;        return getans(mid+1,r,k-ss);    }}int main(){    scanf("%d",&n);    tot=360000*2*18;    prepare();    block=sqrt(n)+1;    fo(i,1,n){        int x;        scanf("%d",&x);        int u=(i-1)/block+1,v=(i-1)%block+1;        inse(0,lim,root[u][v-1],root[u][v],a[u][v]=x,1);    }    int u=(n-1)/block;    fo(i,1,u){        next[i]=i+1;        s[i]=block;    }    int tim=0;    s[u+1]=n-u*block;    m=u+1;    scanf("%d",&q);    fo(haha,1,q){        char ch;        while(ch=getchar(),ch<'A'||ch>'Z');        if (ch=='Q'){            int x,y,k;            scanf("%d%d%d",&x,&y,&k);            x^=lastans;            y^=lastans;            k^=lastans;            find(x,u1,v1);            find(y,u2,v2);            for(int i=u1;i!=u2;i=next[i])rt[i]=root[i][s[i]];            lastans=getans(0,lim,k);            printf("%d\n",lastans);            tim++;        }        if (ch=='M'){            int x,val;            scanf("%d%d",&x,&val);            x^=lastans;            val^=lastans;            find(x,u1,v1);            a[u1][v1]=val;            fo(i,v1,s[u1]){                clear(root[u1][i]);                inse(0,lim,root[u1][i-1],root[u1][i],a[u1][i],1);            }        }        if (ch=='I'){            int x,val;            scanf("%d%d",&x,&val);            x^=lastans;            val^=lastans;            find(x,u1,v1);            if (s[u1]+1<block*2){                s[u1]++;                fd(i,s[u1],v1+1)a[u1][i]=a[u1][i-1];                a[u1][v1]=val;                fo(i,v1,s[u1]){                    clear(root[u1][i]);                    inse(0,lim,root[u1][i-1],root[u1][i],a[u1][i],1);                }            }            else{                if (v1<=block){                    s[++m]=block;                    fo(i,1,block)                    inse(0,lim,root[m][i-1],root[m][i],a[m][i]=a[u1][i+block-1],1);                    s[u1]=block;                    next[m]=next[u1];                    next[u1]=m;                    fd(i,s[u1],v1+1)a[u1][i]=a[u1][i-1];                    a[u1][v1]=val;                    fo(i,v1,s[u1]){                        clear(root[u1][i]);                        inse(0,lim,root[u1][i-1],root[u1][i],a[u1][i],1);                    }                }                else{                    s[++m]=block;                    v1-=block;                    fo(i,1,v1-1){                        a[m][i]=a[u1][i+block];                        inse(0,lim,root[m][i-1],root[m][i],a[m][i],1);                    }                    a[m][v1]=val;                    inse(0,lim,root[m][v1-1],root[m][v1],val,1);                    fo(i,v1+1,block){                        a[m][i]=a[u1][i+block-1];                        inse(0,lim,root[m][i-1],root[m][i],a[m][i],1);                    }                    s[u1]=block;                    next[m]=next[u1];                    next[u1]=m;                }            }        }    }    return 0;}

好吧,vfleaking说正解是这样的:http://vfleaking.blog.163.com/blog/static/1748076342013123659818/

0 0