求助,线段树套Splay
查看原帖
求助,线段树套Splay
759821
syzxzqy楼主2023/7/14 22:08

样例错误,输出"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);
}
2023/7/14 22:08
加载中...