luogu P5494 【模板】线段树分裂

操作过程在那里写的非常清楚了,这里主要粘一下代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>

using namespace std;

typedef long long LL;
const int N=200009;
int n,m,rt[N],bin[N*32],cnt,Index=1;
struct Tree
{
	int l,r;
	LL siz;
	#define l(x) a[x].l
	#define r(x) a[x].r
	#define siz(x) a[x].siz
}a[N*40];

void recycle(int x)
{
	bin[++bin[0]]=x;
	l(x)=r(x)=siz(x)=0;
}

int New() { return bin[0]>0?bin[bin[0]--]:++cnt; }

void push_up(int k) { siz(k)=siz(l(k))+siz(r(k)); }

void Modify(int &k,int l,int r,int x,LL y)
{
	if(!k) k=New();
	if(l==r)
	{
		siz(k)+=y;
		return;
	}
	int mid=l+r>>1;
	if(mid>=x)
		Modify(l(k),l,mid,x,y);
	else
		Modify(r(k),mid+1,r,x,y);
	push_up(k);
}

void init()
{
	scanf("%d %d",&n,&m);
	for (int i=1;i<=n;i++)
	{
		LL x;
		scanf("%lld",&x);
		Modify(rt[1],1,n,i,x);
	}
}

LL Querysum(int k,int l,int r,int x,int y)
{
	if(!k) return 0;
	if(l>=x&&r<=y)
		return siz(k);
	int mid=l+r>>1;
	LL res=0;
	if(mid>=x)
		res+=Querysum(l(k),l,mid,x,y);
	if(mid<y)
		res+=Querysum(r(k),mid+1,r,x,y);
	return res;
}

int QueryKth(int k,int l,int r,int x)
{
	if(l==r)
		return l;
	int mid=l+r>>1;
	if(siz(l(k))>=x)
		return QueryKth(l(k),l,mid,x);
	return QueryKth(r(k),mid+1,r,x-siz(l(k)));
}

int merge(int x,int y)
{
	if(!x||!y) return x+y;
	siz(x)+=siz(y);
	l(x)=merge(l(x),l(y));
	r(x)=merge(r(x),r(y));
	recycle(y);
	return x;
}

void split(int x,int &y,LL k)
{
	y=New();
	if(siz(l(x))<k)
		split(r(x),r(y),k-siz(l(x)));
	else
		swap(r(x),r(y));
	if(siz(l(x))>k)
		split(l(x),l(y),k);
	siz(y)=siz(x)-k;
	siz(x)=k;
}

void work()
{
	LL opt,x,y,z;
	while(m--)
	{
		scanf("%lld",&opt);
		if(opt==2)
		{
			scanf("%lld %lld %lld",&x,&y,&z);
			Modify(rt[x],1,n,z,y);
		}
		else if(opt==3)
		{
			scanf("%lld %lld %lld",&x,&y,&z);
			printf("%lld\n",Querysum(rt[x],1,n,y,z));
		}
		else if(opt==4)
		{
			scanf("%lld %lld",&x,&y);
			if(siz(rt[x])<y)
				puts("-1");
			else
				printf("%d\n",QueryKth(rt[x],1,n,y));
		}
		else if(opt==1)
		{
			scanf("%lld %lld",&x,&y);
			rt[x]=merge(rt[x],rt[y]);
		}
		else
		{
			scanf("%lld %lld %lld",&x,&y,&z);
			LL k1=Querysum(rt[x],1,n,1,y-1),k2=Querysum(rt[x],1,n,y,z);
			int tmp;
			split(rt[x],rt[++Index],k1);
			split(rt[Index],tmp,k2);
			rt[x]=merge(rt[x],tmp);
		}
	}
}

int main()
{
	init();
	work();
	return 0;
}
posted @ 2020-06-11 01:33  With_penguin  阅读(87)  评论(0编辑  收藏  举报