样例错误,输出"0 0 3 49 32"。
Splay 是对的。
记录
但套了线段树,添加了修改 root,不知道有没有错。
希望某位大神能看出本蒻蒟的错误。
代码:
#include <bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int i,op,n,T,w[N],l,r,k,pos,ncnt,root[N<<2];
struct no{
int ch[2],p,v,size;
}tr[N<<5];
inline bool chk(int x){//判断当前节点为左儿子还是右儿子
return tr[tr[x].p].ch[1]==x;
}
inline void pushup(int x){//更改权值数
tr[x].size=tr[tr[x].ch[0]].size+tr[tr[x].ch[1]].size+1;
}
inline void rotate(int x){//单旋
int y=tr[x].p,z=tr[y].p,k=chk(x),w=tr[x].ch[k^1];
tr[y].ch[k]=w;tr[w].p=y;
tr[z].ch[chk(y)]=x;tr[x].p=z;
tr[x].ch[k^1]=y;tr[y].p=x;
pushup(y);pushup(x);
}
inline void splay(int &root,int x,int goal=0){//把x节点旋转到goal节点
while(tr[x].p!=goal){
int y=tr[x].p,z=tr[y].p;
if(z!=goal)
rotate(chk(x)==chk(y)?y:x);
rotate(x);
}
if(!goal) root=x;
}
inline void insert(int &root,int x){//插入x
int cur=root,p=0;
while(cur)
p=cur,cur=tr[cur].ch[x>tr[cur].v];
cur=++ncnt;
// cout<<cur<<" "<<p<<"\n";
tr[p].ch[x>tr[p].v]=cur;
tr[cur].ch[0]=tr[cur].ch[1]=0;
tr[cur].p=p;tr[cur].v=x;
tr[cur].size=1;
splay(root,cur);
}
inline void find(int &root,int x){//把x旋转到根节点
int cur=root;
while(tr[cur].ch[x>tr[cur].v]&&x!=tr[cur].v)
cur=tr[cur].ch[x>tr[cur].v];
splay(root,cur);
}
inline int getrank(int &root,int x){//x的排名
find(root,x);
if(tr[root].v>=x) return tr[tr[root].ch[0]].size;
else return tr[tr[root].ch[0]].size+tr[root].size;
}
inline int getpre(int &root,int x){//x的前驱
find(root,x);
if(tr[root].v<x) return root;
int cur=tr[root].ch[0];
while(tr[cur].ch[1]) cur=tr[cur].ch[1];
splay(root,cur);return cur;
}
inline int getsucc(int &root,int x){//x的后继
find(root,x);
if(tr[root].v>x) return root;
int cur=tr[root].ch[1];
while(tr[cur].ch[0]) cur=tr[cur].ch[0];
splay(root,cur);return cur;
}
inline void del(int &root,int v){//删除x
int u=root;
while(u){
if(tr[u].v==v) break;
if(tr[u].v<v) u=tr[u].ch[1];
else u=tr[u].ch[0];
}
splay(root,u,0);
int l=tr[u].ch[0],r=tr[u].ch[1];
while(tr[l].ch[1]) l=tr[l].ch[1];
while(tr[r].ch[0]) r=tr[r].ch[0];
splay(root,l);splay(root,r,l);
tr[r].ch[0]=0;
splay(root,r);
}
void build(int u,int l,int r){//建立线段树
insert(root[u],-2147483647);insert(root[u],2147483647);
for(int i=l;i<=r;++i) insert(root[u],w[i]);
if(l==r) return ;
int mid=(l+r>>1);
build(u<<1,l,mid);build(u<<1|1,mid+1,r);
}
int queryrank(int u,int l,int r,int x,int y,int v){//区间v的排名
if(x<=l&&r<=y) return getrank(root[u],v)-1;
int mid=(l+r)/2,res=0;
if(x<=mid) res+=queryrank(u<<1,l,mid,x,y,v);
if(y>mid) res+=queryrank(u<<1|1,mid+1,r,x,y,v);
return res;
}
int querykth(int x,int y,int k){//求区间第k小
int l=0,r=1e8,ans=0,mid;
while(l<=r){
mid=l+r>>1;//queryrank(1,1,n,x,y,mid);//+1<<"\n";
if(queryrank(1,1,n,x,y,mid)+1<=k) l=mid+1,ans=mid;
else r=mid-1;
}
return ans;
}
void change(int u,int l,int r,int pos,int v){//修改w[pos]的值
del(root[u],w[pos]);
insert(root[u],v);
if(l==r) return ;
int mid=l+r>>1;
if(pos<=mid) change(u<<1,l,mid,pos,v);
else change(u<<1|1,mid+1,r,pos,v);
}
int querypre(int u,int l,int r,int x,int y,int v){
if(x<=l&&r<=y) return getpre(root[u],v);
int mid=l+r>>1,res=-2147483647;
if(x<=mid) res=max(res,querypre(u<<1,l,mid,x,y,v));
if(y>mid) res=max(res,querypre(u<<1|1,mid+1,r,x,y,v));
return res;
}
int querysucc(int u,int l,int r,int x,int y,int v){
if(x<=l&&r<=y) return getsucc(root[u],v);
int mid=l+r>>1,res=2147483647;
if(x<=mid) res=min(res,querysucc(u<<1,l,mid,x,y,v));
if(y>mid) res=min(res,querysucc(u<<1|1,mid+1,r,x,y,v));
return res;
}
int main(){
// ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
cin>>n>>T;
for(i=1;i<=n;++i) cin>>w[i];
build(1,1,n);
while(T--){
cin>>op;
if(op==1) cin>>l>>r>>k,cout<<queryrank(1,1,n,l,r,k)+1<<"\n";
if(op==2) cin>>l>>r>>k,cout<<querykth(l,r,k)<<"\n";
if(op==3) cin>>pos>>k,change(1,1,n,pos,k),w[pos]=k;
if(op==4) cin>>l>>r>>k,cout<<querypre(1,1,n,l,r,k)<<"\n";
if(op==5) cin>>l>>r>>k,cout<<querysucc(1,1,n,l,r,k)<<"\n";
}
// for(i=1;i<=11;++i) cout<<i<<" "<<tr[i].v<<" "<<tr[i].p<<" "<<tr[i].ch[0]<<" "<<tr[i].ch[1]<<"\n";
// cout<<getsucc(root[1],4);
}