Description
您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:
1.查询 x在区间内的排名;
2.查询区间内排名为 k 的值;
3.修改某一位置上的数值;
4.查询 x 在区间内的前趋(前趋定义为小于 x,且最大的数);
5.查询 x 在区间内的后继(后继定义为大于 x,且最小的数)。
Input
第一行两个数 n,m,表示长度为 n 的有序序列和 m 个操作。
第二行有 n个数,表示有序序列。
下面有 m 行,每行第一个数表示操作类型:
1.之后有三个数 l,r,x表示查询 x在区间 [l,r] 的排名;
2.之后有三个数 l,r,k表示查询区间 [l,r]内排名为 k的数;
3.之后有两个数 pos,x表示将 pos位置的数修改为 x;
4.之后有三个数 l,r,x表示查询区间 [l,r]内 x 的前趋;
5.之后有三个数 l,r,x表示查询区间 [l,r]内 x 的后继。
Output
对于操作 1,2,4,5各输出一行,表示查询结果。
Sample Input
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
Sample Output
2
4
3
4
9
Hint
1≤n,m≤5×10^4 ,−10^8 ≤k,x≤10^8
树套树的模板题,调了lz4天= =各种错误都写出来了,我也不知道该说什么好。
#include<bits/stdc++.h>
using namespace std;
inline int Getint(){register int re=0,f=1;register char c;while(c=getchar(),(c>='0'&&c<='9')^1)f=c^'-';while(re=(re<<1)+(re<<3)+(c^48),c=getchar(),(c>='0'&&c<='9'));return f?re:-re;}
#define Inc(i,L,r) for(register int i=(L);i<=(r);++i)
const int N = 5e4+10,Maxsiz = N*log2(N)*2;
int n,m,a[N];
struct Splay{
int p[Maxsiz],ch[Maxsiz][2];
int ct,vl[Maxsiz],siz[Maxsiz],cnt[Maxsiz];
#define Ls(x) ch[x][0]
#define rs(x) ch[x][1]
#define maintain(x) siz[x]=siz[Ls(x)]+siz[rs(x)]+cnt[x]
inline void rotate(int x){
int f=p[x],gf=p[f],tp=rs(f)==x,son=ch[x][!tp];
ch[p[son]=f][tp]=son,maintain(f);
ch[p[f]=x][!tp]=f,maintain(x);
ch[p[x]=gf][rs(gf)==f]=x;
}
inline void splay(int x,int goal,int &root){
if(x==goal)return ;
while(p[x]^goal){
if((p[p[x]]^goal)&&((rs(p[p[x]])==p[x])==(rs(p[x])==x)))rotate(p[x]);
rotate(x);
}
if(!goal)root=x;
}
inline void newnode(int x,int k,int Fa){
siz[x]=cnt[x]=1;vl[x]=k;p[x]=Fa;
}
inline void insert(int &x,int k,int Fa,int &root){
if(vl[x]==k)return ++cnt[x],splay(x,0,root),void();
if(!x)return newnode(x=++ct,k,Fa),splay(x,0,root),void();
insert(ch[x][vl[x]<k],k,x,root);
}
inline int findpre(int x){
for(x=Ls(x);rs(x);x=rs(x));
return x;
}
inline int findsub(int x){
for(x=rs(x);Ls(x);x=Ls(x));
return x;
}
inline void delet(int k,int &root){
int x;for(x=root;vl[x]^k;vl[x]>k?x=Ls(x):x=rs(x));
--cnt[x],splay(x,0,root);
if(cnt[x]>=1)return ;
int pre=findpre(x),sub=findsub(x);
splay(pre,0,root),splay(sub,root,root);
Ls(sub)=0,maintain(sub),maintain(pre);
}
inline int getrank(int x,int k){
int tot=0;
while(x)vl[x]<k?tot+=siz[Ls(x)]+cnt[x],x=rs(x):x=Ls(x);
return tot-1;
}
inline int getpre(int x,int k){
int ans=-(1<<30);
for(;x;vl[x]>=k?x=Ls(x):x=rs(x))if(vl[x]<k&&vl[x]>ans)ans=vl[x];
return ans;
}
inline int getsub(int x,int k){
int ans=(1<<30);
for(;x;vl[x]<=k?x=rs(x):x=Ls(x))if(vl[x]>k&&vl[x]<ans)ans=vl[x];
return ans;
}
}sp;
struct SegMent{
struct tree{
int L,r,rt;
}t[N<<2];
#define Lc v<<1
#define rc v<<1|1
inline int getsub(int v,int A,int b,int k){
if(t[v].L>b||t[v].r<A)return (1<<30);
if(A<=t[v].L&&t[v].r<=b)return sp.getsub(t[v].rt,k);
return min(getsub(Lc,A,b,k),getsub(rc,A,b,k));
}
inline int getpre(int v,int A,int b,int k){
if(t[v].L>b||t[v].r<A)return -(1<<30);
if(A<=t[v].L&&t[v].r<=b)return sp.getpre(t[v].rt,k);
return max(getpre(Lc,A,b,k),getpre(rc,A,b,k));
}
inline void modify(int v,int A,int b,int k,int cmd){
if(t[v].L>b||t[v].r<A)return ;
~cmd?sp.insert(t[v].rt,k,0,t[v].rt):sp.delet(k,t[v].rt);
if(A<=t[v].L&&t[v].r<=b)return ;
modify(Lc,A,b,k,cmd),modify(rc,A,b,k,cmd);
}
inline int getrank(int v,int A,int b,int k){
if(t[v].L>b||t[v].r<A)return 0;
if(A<=t[v].L&&t[v].r<=b)return sp.getrank(t[v].rt,k);
return getrank(Lc,A,b,k)+getrank(rc,A,b,k);
}
inline void build(int v,int L,int r){
int Mid=L+r>>1;
t[v]=(tree){L,r,0};
sp.insert(t[v].rt,-(1<<30),0,t[v].rt);
Inc(i,L,r)sp.insert(t[v].rt,a[i],0,t[v].rt);
sp.insert(t[v].rt,(1<<30),0,t[v].rt);
if(L==r)return ;
build(Lc,L,Mid),build(rc,Mid+1,r);
}
}tr;
inline void init(){
n=Getint(),m=Getint();
Inc(i,1,n)a[i]=Getint();
}
inline int getrank(int L,int r,int k){
return tr.getrank(1,L,r,k)+1;
}
inline int getkth(int A,int b,int kth){
int ans;for(int x=tr.t[1].rt;x;){
if(tr.getrank(1,A,b,sp.vl[x])<kth)ans=sp.vl[x],x=sp.rs(x);
else x=sp.Ls(x);
}
return ans;
}
inline void modify(){
int x=Getint(),k=Getint();
tr.modify(1,x,x,a[x],-1);
a[x]=k;
tr.modify(1,x,x,a[x],1);
}
inline void solv(){
memset(sp.vl,63,sizeof(sp.vl));
tr.build(1,1,n);
Inc(i,1,m){
int op=Getint(),L,r,k;
if(op^3)L=Getint(),r=Getint(),k=Getint();
if(op==1)cout<<getrank(L,r,k)<<"\n";
if(op==2)cout<<getkth(L,r,k)<<"\n";
if(op==3)modify();
if(op==4)cout<<tr.getpre(1,L,r,k)<<"\n";
if(op==5)cout<<tr.getsub(1,L,r,k)<<"\n";
}
}
int main(){
// freopen("erbi.in","r",stdin);
// freopen("erbi.out","w",stdout);
init();
solv();
return 0;
}