线段树分裂求调
  • 板块学术版
  • 楼主_Ch1F4N_
  • 当前回复0
  • 已保存回复0
  • 发布时间2023/7/15 07:53
  • 上次更新2023/11/3 09:47:02
查看原帖
线段树分裂求调
520748
_Ch1F4N_楼主2023/7/15 07:53

如题,但是我写的线段树是维护线段树上叶子结点构成的虚树。

#include<bits/stdc++.h>
#define pll pair<int,int>
#define int long long
using namespace std;
const int maxn = 1e6+114;

int tot;
stack<int> brush;
struct Node{
    int ls,rs;
    int sum;
    int l,r;
}tree[maxn];
int clone(){
	int New;
	if(brush.size()>0){
		New=brush.top();
		brush.pop();
	}
	else{
		New=++tot;
	}
	tree[New].l=tree[New].r=tree[New].sum=tree[New].ls=tree[New].rs=0;
	return New;
}
int root[maxn];
bool check(int u,int v,int len){
    return ((u-1)/(1<<len)+1==(v-1)/(1<<len)+1);
}
inline pll LCA(int u,int v){
    int l=-1,r=20;
    while(l+1<r){
        int mid=(l+r)/2;
        if(check(u,v,mid)==true) r=mid;
        else l=mid;
    }
    int posu=(u-1)/(1<<r)+1;
    return make_pair((posu-1)*(1<<r)+1,posu*(1<<r));
}
inline void pushup(int x){
    tree[x].sum=tree[tree[x].ls].sum+tree[tree[x].rs].sum;
}
inline void add(int x,int pos,int v){
    int mid=(tree[x].l+tree[x].r)>>1;
    if(pos<=mid){
        if(tree[x].ls==0){
        	int y=clone();
            tree[x].ls=y;
            tree[y].sum+=v;
            tree[y].l=tree[y].r=pos;
            pushup(x);
            return ;
        }
        else{
            if(tree[tree[x].ls].l==tree[tree[x].ls].r){
                if(tree[tree[x].ls].l==pos){
                    tree[tree[x].ls].sum+=v;
                    pushup(x);
                    return ;
                }
                pair<int,int> lca=LCA(pos,tree[tree[x].ls].l);
                int y=clone();
                tree[y].l=lca.first;
                tree[y].r=lca.second;
                int A=y;
                int B=tree[x].ls;
                int z=clone();
                tree[z].sum+=v;
                tree[z].l=tree[z].r=pos;
                int C=z;
                tree[x].ls=A;
                if(tree[B].l>tree[C].l) swap(B,C);
                tree[A].ls=B;
                tree[A].rs=C;
                pushup(A);
                pushup(x);
                return ;
            }
            else{
                if(pos>tree[tree[x].ls].r||pos<tree[tree[x].ls].l){
                    pair<int,int> lca=LCA(pos,tree[tree[x].ls].r);
                    int y=clone();
                    tree[y].l=lca.first;
                    tree[y].r=lca.second;
                    int A=y;
                    int B=tree[x].ls;
                    int z=clone();
                    tree[z].sum+=v;
                    tree[z].l=tree[z].r=pos;
                    int C=z;
                    tree[x].ls=A;
                    if(tree[B].l>tree[C].l) swap(B,C);
                    tree[A].ls=B;
                    tree[A].rs=C;
                    pushup(A);
                    pushup(x);
                }
                else{
                    add(tree[x].ls,pos,v);
                    pushup(x);
                    return ;
                }
            }
        }
    }
    else{
        if(tree[x].rs==0){
        	int y=clone();
            tree[x].rs=y;
            tree[y].sum+=v;
            tree[y].l=tree[y].r=pos;
            pushup(x);
            return ;
        }
        else{
            if(tree[tree[x].rs].l==tree[tree[x].rs].r){
                if(tree[tree[x].rs].r==pos){
                    tree[tree[x].rs].sum+=v;
                    pushup(x);
                    return ;
                }
                pair<int,int> lca=LCA(pos,tree[tree[x].rs].l);
                int y=clone();
                tree[y].l=lca.first;
                tree[y].r=lca.second;
                int A=y;
                int B=tree[x].rs;
                int z=clone();
                tree[z].sum+=v;
                tree[z].l=tree[z].r=pos;
                int C=z;
                tree[x].rs=A;
                if(tree[B].l>tree[C].l) swap(B,C);
                tree[A].ls=B;
                tree[A].rs=C;
                pushup(A);
                pushup(x);
                return ;
            }
            else{
                if(pos<tree[tree[x].rs].l||pos>tree[tree[x].rs].r){
                    pair<int,int> lca=LCA(pos,tree[tree[x].rs].l);
                    int y=clone();
                    tree[y].l=lca.first;
                    tree[y].r=lca.second;
                    int A=y;
                    int B=tree[x].rs;
                    int z=clone();
                    tree[z].sum+=v;
                    tree[z].l=tree[z].r=pos;
                    int C=z;
                    tree[x].rs=A;
                    if(tree[C].l>tree[B].l) swap(C,B);
                    tree[A].ls=C;
                    tree[A].rs=B;
                    pushup(A);
                    pushup(x);
                }
                else{
                    add(tree[x].rs,pos,v);
                    pushup(x);
                    return ;
                }
            }
        }
    }
}
inline int query(int x,int l,int r){
	int lt=tree[x].l;
	int rt=tree[x].r;
    if(x==0) return 0;
	if(rt<l||r<lt){
		return 0;
	}
	if(l<=lt&&rt<=r){
		return tree[x].sum;
	}
    int res=0,mid=(lt+rt)>>1;
    res+=query(tree[x].ls,l,r);
    res+=query(tree[x].rs,l,r);    	
    return res;
}
int merge(int a,int b){
	if(a==0||b==0) return a+b;
	if((tree[a].r-tree[a].l+1)<(tree[b].r-tree[b].l+1)) swap(a,b);
	if(tree[a].l==tree[b].l&&tree[a].r==tree[b].r){
		if(tree[a].l==tree[a].r){
			tree[a].sum+=tree[b].sum;
			brush.push(b);
			return a;
		}
		int L=tree[b].ls,R=tree[b].rs;
		brush.push(b);
		tree[a].ls=merge(tree[a].ls,L);
		tree[a].rs=merge(tree[a].rs,R);
		pushup(a);
		return a;
	}	
	if(tree[a].l<=tree[b].l&&tree[b].r<=tree[a].r){
		if(tree[b].l==tree[b].r){
			add(a,tree[b].l,tree[b].sum);
			return a;
		}
		int L=tree[b].ls,R=tree[b].rs;
		brush.push(b);
		tree[a].ls=merge(tree[a].ls,L);
		tree[a].rs=merge(tree[a].rs,R);
		pushup(a);
		return a;
	}
    pair<int,int> lca=LCA(tree[a].l,tree[b].l);
    int y=clone();
    tree[y].l=lca.first;
    tree[y].r=lca.second;
    if(tree[a].l>tree[b].l) swap(a,b);
    tree[y].ls=a;
    tree[y].rs=b;
    pushup(y);
    return y;
}
inline void maintain(int &x){	 
	if(tree[x].l!=1&&tree[x].r!=(1<<20)){
		int y=clone();
		tree[y].l=1,tree[y].r=(1<<20);
		int mid=(tree[y].l+tree[y].r)>>1;
		if(!x){
			x=y;
			return ;
		}
		if(tree[x].r<=mid){
			tree[y].ls=x;
		}
		else{
			tree[y].rs=x;
		}
		pushup(y);
		x=y;
	}
	return ;
}
inline void split(int &x,int &y,int l,int r){
	if(!x) return ;
	int lt=tree[x].l,rt=tree[x].r;
	//cout<<lt<<' '<<rt<<' '<<l<<' '<<r<<'\n';
	if(rt<l||r<lt) return ;
	if(l<=lt&&rt<=r){
		y=x;
		x=0;
		return ;
	}
	if(!y) y=clone();
	split(tree[x].ls,tree[y].ls,l,r);
	split(tree[x].rs,tree[y].rs,l,r);
	if(tree[y].ls==0&&tree[y].rs==0){
		brush.push(y);
		y=0;
	}
	else if(tree[y].ls==0){
		brush.push(y);
		y=tree[y].rs;
	}
	else if(tree[y].rs==0){
		brush.push(y);
		y=tree[y].ls;
	}
	else{
		pair<int,int> lca=LCA(tree[tree[y].ls].l,tree[tree[y].rs].l);
		tree[y].l=lca.first,tree[y].r=lca.second;
		pushup(y);
	}
	if(tree[x].ls==0&&tree[x].rs==0){
		brush.push(x);
		x=0;
	}
	else if(tree[x].ls==0){
		brush.push(x);
		x=tree[x].rs;
	}
	else if(tree[x].rs==0){
		brush.push(x);
		x=tree[x].ls;
	}
	else{
		pair<int,int> lca=LCA(tree[tree[x].ls].l,tree[tree[x].rs].l);
		tree[x].l=lca.first,tree[x].r=lca.second;
		pushup(x);
	}
	return ;
}
inline int kth(int x,int k){
	if(tree[x].l==tree[x].r) return tree[x].l;
	if(k<=tree[tree[x].ls].sum) return kth(tree[x].ls,k);
	else return kth(tree[x].rs,k-tree[tree[x].ls].sum);
} 
void dfs(int x){
    if(x==0) return ;
    dfs(tree[x].ls);
    cout<<tree[x].l<<' '<<tree[x].r<<' '<<tree[x].sum<<'\n';
    dfs(tree[x].rs);
}
void init(int pos){
    root[pos]=clone();
    tree[root[pos]].l=1;
    tree[root[pos]].r=(1<<20);
}
int n,m;
int cnt;
int zyb;
signed main(){
//freopen("1.in","r",stdin);
//freopen("1.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n>>m;
cnt++;
init(cnt);
for(int i=1;i<=n;i++){
	int x;
	cin>>x;
	add(root[cnt],i,x);
}
while(m--){
	int opt;
	cin>>opt;
	if(opt==0){
		int x,y,z;
		cin>>x>>y>>z;
		cnt++;
		split(root[x],root[cnt],y,z);
		maintain(root[x]);
		maintain(root[cnt]);
	}
	else if(opt==1){
		int x,y;
		cin>>x>>y;
		root[x]=merge(root[x],root[y]);
	}
	else if(opt==2){
		int x,y,z;
		cin>>x>>y>>z;
		add(root[x],z,y);
	}
	else if(opt==3){
		zyb++;
		int x,y,z;
		cin>>x>>y>>z;
		cout<<query(root[x],y,z)<<'\n';
	} 
	else{
		int x,y;
		cin>>x>>y;
		if(tree[root[x]].sum<y){
			cout<<"-1\n";
		}
		else{
			cout<<kth(root[x],y)<<'\n';
		}
	}
}
return 0;
}
2023/7/15 07:53
加载中...