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;
}
由于博主比较菜,所以有很多东西待学习,大部分文章会持续更新,另外如果有出错或者不周之处,欢迎大家在评论中指出!