loj #106. 二逼平衡树
#106. 二逼平衡树
内存限制:512 MiB时间限制:4000 ms标准输入输出
题目类型:传统评测方式:文本比较
这是一道模板题。
您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:
- 查询 x 在区间内的排名;
- 查询区间内排名为 k 的值;
- 修改某一位置上的数值;
- 查询 x 在区间内的前趋(前趋定义为小于 x,且最大的数);
- 查询 x 在区间内的后继(后继定义为大于 x ,且最小的数)。
输入格式
第一行两个数 n,m,表示长度为 n 的有序序列和 m 个操作。
第二行有 n个数,表示有序序列。
下面有 m行,每行第一个数表示操作类型:
- 之后有三个数 l,r,x表示查询 x 在区间 [l,r]的排名;
- 之后有三个数 l,r,k 表示查询区间 [l,r] 内排名为 k 的数;
- 之后有两个数 pos,x表示将 pos位置的数修改为 x;
- 之后有三个数 l,r,x 表示查询区间 [l,r]内 x的前趋;
- 之后有三个数 l,r,x 表示查询区间 [l,r] 内 x的后继.
输出格式
对于操作 1,2,4,5各输出一行,表示查询结果。
样例
样例输入
9 6
4 2 2 1 9 4 0 1 1
2 1 4 3
3 4 10
2 1 4 3
1 2 5 9
4 3 9 5
5 2 8 5
样例输出
2
4
3
4
9
数据范围与提示
1≤n,m≤5e4 −1e8≤k,x≤1e8
#include <bits/stdc++.h> #define pt ch[ch[root][1]][0] const int MAXN=1e5+10; const int inf=1e8+10; using namespace std; int n; int ch[MAXN<<7][2],size[MAXN<<7],pre[MAXN<<7],key[MAXN<<7],cnt2=0,psize; int rt[MAXN],a[MAXN]; vector<int>vec; void Treavel(int x) { if(x) { Treavel(ch[x][0]); printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size=%2d,key=%2d\n",x,ch[x][0],ch[x][1],pre[x],size[x],key[x]); Treavel(ch[x][1]); } } void debug(int rp) { printf("root:%d\n",rp); Treavel(rp); } typedef struct node{ int root,maxx; void newnode(int &x,int fa,int vul){ x=++cnt2;ch[x][0]=ch[x][1]=0;pre[x]=fa;key[x]=vul; size[x]=1; } void inte(){ root=0; newnode(root,0,-inf); newnode(ch[root][1],root,inf); } void up(int x){size[x]=size[ch[x][0]]+size[ch[x][1]]+1;} void rotate(int x,int kind){ int y=pre[x]; ch[y][!kind]=ch[x][kind];pre[ch[x][kind]]=y; if(pre[y]) ch[pre[y]][ch[pre[y]][1]==y]=x; pre[x]=pre[y];ch[x][kind]=y;pre[y]=x; up(y); } void splay(int x,int goal){ while(pre[x]!=goal){ if(pre[pre[x]]==goal) rotate(x,ch[pre[x]][0]==x); else{ int y=pre[x];int kind=ch[pre[y]][0]==y; if(ch[y][kind]==x) rotate(x,!kind),rotate(x,kind); else rotate(y,kind),rotate(x,kind); } } if(goal==0) root=x; up(x); } void insert(int &x,int vul,int fa){ if(!x){newnode(x,fa,vul);return ;} if(key[x]>vul) insert(ch[x][0],vul,x); else insert(ch[x][1],vul,x); up(x); } int find1(int x,int vul){ if(key[x]==vul) return x; else if(key[x]<vul) return find1(ch[x][1],vul); else return find1(ch[x][0],vul); } int find2(int x,int siz){ if(siz==size[ch[x][0]]+1) return x; else if(siz<=size[ch[x][0]]) return find2(ch[x][0],siz); else return find2(ch[x][1],siz-size[ch[x][0]]-1); } void erase(int vul){ splay(find1(root,vul),0); int t=size[ch[root][0]]+1; splay(find2(root,t-1),0); splay(find2(root,t+1),root); pre[ch[ch[root][1]][0]]=0;ch[ch[root][1]][0]=0;up(ch[root][1]);up(root); } void pre_vul(int x,int vul){ if(!x) return ; if(key[x]>=vul) pre_vul(ch[x][0],vul); else{ if(vul-key[x]<=vul-maxx) maxx=key[x],pre_vul(ch[x][1],vul); else pre_vul(ch[x][1],vul); } } void last_vul(int x,int vul){ if(!x) return ; if(key[x]<=vul) last_vul(ch[x][1],vul); else{ if(key[x]-vul<=maxx-vul) maxx=key[x],last_vul(ch[x][0],vul); else last_vul(ch[x][0],vul); } } }node; typedef struct wjy{ int l,r,sum; }wjy; wjy dd[MAXN<<7];int cnt1=0; typedef struct List{ node T; }List; List d[MAXN<<2]; void built(int &x,int y,int l,int r,int vul,int flag){ x=++cnt1;dd[x]=dd[y];dd[x].sum+=flag; if(l==r) return ; int mid=(l+r)>>1; if(vul<=mid) built(dd[x].l,dd[y].l,l,mid,vul,flag); else built(dd[x].r,dd[y].r,mid+1,r,vul,flag); } int ans; vector<int>vv1; vector<int>vv2; int get_id(int x){return x&(-x);} void slove(int l,int r){ for(int i=l-1;i>0;i-=get_id(i)) vv2.push_back(rt[i]); for(int i=r;i>0;i-=get_id(i)) vv1.push_back(rt[i]); } int querty1(int l,int r,int ql,int qr,int vul){ slove(ql,qr); while(l<r){ int mid=(l+r)>>1; if(mid<=vul){ l=mid+1; for(int i=0;i<vv1.size();i++) ans+=dd[dd[vv1[i]].l].sum; for(int i=0;i<vv2.size();i++) ans-=dd[dd[vv2[i]].l].sum; for(int i=0;i<vv1.size();i++) vv1[i]=dd[vv1[i]].r; for(int i=0;i<vv2.size();i++) vv2[i]=dd[vv2[i]].r; } else{ r=mid; for(int i=0;i<vv1.size();i++) vv1[i]=dd[vv1[i]].l; for(int i=0;i<vv2.size();i++) vv2[i]=dd[vv2[i]].l; } } return ans; } int querty2(int l,int r,int ql,int qr,int k){ slove(ql,qr); int t; while(l<r){ int mid=(l+r)>>1;t=0; for(int i=0;i<vv1.size();i++) t+=dd[dd[vv1[i]].l].sum; for(int i=0;i<vv2.size();i++) t-=dd[dd[vv2[i]].l].sum; if(t>=k){ r=mid; for(int i=0;i<vv1.size();i++) vv1[i]=dd[vv1[i]].l; for(int i=0;i<vv2.size();i++) vv2[i]=dd[vv2[i]].l; } else{ l=mid+1;k-=t; for(int i=0;i<vv1.size();i++) vv1[i]=dd[vv1[i]].r; for(int i=0;i<vv2.size();i++) vv2[i]=dd[vv2[i]].r; } } return l; } void update1(int root,int l,int r,int vul,int t,int flag){ //cout<<l<<" "<<r<<endl; //cout<<d[root].T.root<<endl; if(flag) d[root].T.insert(d[root].T.root,vul,0); else d[root].T.erase(vul); //if(!flag) debug(d[root].T.root); if(l==r) return ; int mid=(l+r)>>1; if(t<=mid) update1(root<<1,l,mid,vul,t,flag); else update1(root<<1|1,mid+1,r,vul,t,flag); } int maxn; void querty(int root,int l,int r,int ql,int qr,int x,int flag){ if(ql<=l&&r<=qr){ if(flag) d[root].T.maxx=-1*inf,d[root].T.pre_vul(d[root].T.root,x),maxn=max(maxn,d[root].T.maxx); else d[root].T.maxx=inf,d[root].T.last_vul(d[root].T.root,x),maxn=min(maxn,d[root].T.maxx); return ; } int mid=(l+r)>>1; if(ql<=mid) querty(root<<1,l,mid,ql,qr,x,flag); if(qr>mid) querty(root<<1|1,mid+1,r,ql,qr,x,flag); } void inte(){ for(int i=1;i<=(n<<2);i++) d[i].T.inte(); for(int i=1;i<=n;i++){ for(int j=i;j<=n;j+=get_id(j)){ built(rt[j],rt[j],1,psize,a[i],1); } update1(1,1,n,a[i],i,1); } } void update(int pos,int x,int y){ for(int j=pos;j<=n;j+=get_id(j)){ built(rt[j],rt[j],1,psize,x,-1); built(rt[j],rt[j],1,psize,y,1); } update1(1,1,n,x,pos,0); //cout<<"sb"<<endl; update1(1,1,n,y,pos,1); //cout<<"sb"<<endl; } int slove1(int l,int r,int x){ ans=0; int ans1=querty1(1,psize,l,r,x-1); vv1.clear();vv2.clear(); return ans1+1; } int slove2(int l,int r,int k){ ans=querty2(1,psize,l,r,k); vv1.clear();vv2.clear(); return ans; } int slove3(int l,int r,int x){ maxn=-1*inf;querty(1,1,n,l,r,x,1); return maxn; } int slove4(int l,int r,int x){ //cout<<l<<" "<<r<<endl; maxn=inf;querty(1,1,n,l,r,x,0); return maxn; } typedef struct P{ int op,l,r,x; }P; P p[MAXN]; int main(){ int m;scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&a[i]),vec.push_back(a[i]); for(int i=1;i<=m;i++){ scanf("%d",&p[i].op); if(p[i].op==3) scanf("%d%d",&p[i].l,&p[i].x),vec.push_back(p[i].x); else if(p[i].op==2) scanf("%d%d%d",&p[i].l,&p[i].r,&p[i].x); else scanf("%d%d%d",&p[i].l,&p[i].r,&p[i].x),vec.push_back(p[i].x); } sort(vec.begin(),vec.end()); psize=unique(vec.begin(),vec.end())-vec.begin(); for(int i=1;i<=n;i++) a[i]=lower_bound(vec.begin(),vec.begin()+psize,a[i])-vec.begin()+1; inte(); for(int i=1;i<=m;i++){ if(p[i].op==2) continue; p[i].x=lower_bound(vec.begin(),vec.begin()+psize,p[i].x)-vec.begin()+1; } for(int i=1;i<=m;i++){ if(p[i].op==1) printf("%d\n",slove1(p[i].l,p[i].r,p[i].x)); else if(p[i].op==2) printf("%d\n",vec[slove2(p[i].l,p[i].r,p[i].x)-1]); else if(p[i].op==3) update(p[i].l,a[p[i].l],p[i].x),a[p[i].l]=p[i].x; else if(p[i].op==4) printf("%d\n",vec[slove3(p[i].l,p[i].r,p[i].x)-1]); else printf("%d\n",vec[slove4(p[i].l,p[i].r,p[i].x)-1]); } return 0; }