【模板】线段树分裂

  • 涉及到分裂操作,空间不太好算,干脆直接压着上限开:\(100*1024*1024/16\)
#include <bits/stdc++.h>
using namespace std;
const int N=200005;
int a[N];
int root[N],tot,cnt;
struct t1
{
	int l,r;
	long long v;
	t1()
	{
		l=r=v=0;
	}
}t[100*1024*1024/16];
void build(int &p,int l,int r)
{
	if(!p)
	{
		p=++tot;
	}
	if(l==r)
	{
		t[p].v=a[l];
		return;
	}
	int mid=(l+r)>>1;
	build(t[p].l,l,mid);
	build(t[p].r,mid+1,r);
	t[p].v=t[t[p].l].v+t[t[p].r].v;
}
void split(int &p,int &q,int l,int r,int u,int v)
{
	if(!q)
	{
		q=++tot;
	}
	if(u<=l&&v>=r)
	{
		t[q]=t[p];
		p=0;
		return;
	}
	int mid=(l+r)>>1;
	if(u<=mid)
	{
		split(t[p].l,t[q].l,l,mid,u,v);
	}
	if(v>mid)
	{
		split(t[p].r,t[q].r,mid+1,r,u,v);
	}
	t[p].v=t[t[p].l].v+t[t[p].r].v;
	t[q].v=t[t[q].l].v+t[t[q].r].v;
}
int merge(int p,int q,int l,int r)
{
	if(!p)
	{
		return q;
	}
	if(!q)
	{
		return p;
	}
	if(l==r)
	{
		t[p].v+=t[q].v;
		return p;
	}
	int mid=(l+r)>>1;
	t[p].l=merge(t[p].l,t[q].l,l,mid);
	t[p].r=merge(t[p].r,t[q].r,mid+1,r);
	t[p].v=t[t[p].l].v+t[t[p].r].v;
	return p;
}
void change(int &p,int l,int r,int x,int k)
{
	if(!p)
	{
		p=++tot;
	}
	if(l==r)
	{
		t[p].v+=k;
		return;
	}
	int mid=(l+r)>>1;
	if(x<=mid)
	{
		change(t[p].l,l,mid,x,k);
	}
	else
	{
		change(t[p].r,mid+1,r,x,k);
	}
	t[p].v=t[t[p].l].v+t[t[p].r].v;
}
long long ask0(int p,int l,int r,int u,int v)
{
	if(!p)
	{
		return 0;
	}
	if(u<=l&&v>=r)
	{
		return t[p].v;
	}
	int mid=(l+r)>>1;
	long long va=0;
	if(u<=mid)
	{
		va+=ask0(t[p].l,l,mid,u,v);
	}
	if(v>mid)
	{
		va+=ask0(t[p].r,mid+1,r,u,v);
	}
	return va;
}
int ask1(int p,int l,int r,int k)
{
	if(!p)
	{
		return -1;
	}
	if(l==r)
	{
		return l;
	}
	int mid=(l+r)>>1;
	if(k<=t[t[p].l].v)
	{
		return ask1(t[p].l,l,mid,k);
	}
	else
	{
		return ask1(t[p].r,mid+1,r,k-t[t[p].l].v);
	}
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
	}
	build(root[++cnt],1,n);
	for(int i=1;i<=m;i++)
	{
		int opt,p,x,y,t,k;
		cin>>opt>>p;
		switch(opt)
		{
			case 0:
				cin>>x>>y;
				split(root[p],root[++cnt],1,n,x,y);
				break;
			case 1:
				cin>>t;
				merge(root[p],root[t],1,n);
				break;
			case 2:
				cin>>k>>x;
				change(root[p],1,n,x,k);
				break;
			case 3:
				cin>>x>>y;
				cout<<ask0(root[p],1,n,x,y)<<"\n";
				break;
			default:
				cin>>k;
				cout<<ask1(root[p],1,n,k)<<"\n";
				break;
		}
	}
	return 0;
}
posted @ 2025-02-19 15:31  D06  阅读(9)  评论(0)    收藏  举报
//雪花飘落效果