宏定义
- #define pl a[p].tl:节点 p 的左儿子。
- #define pr a[p].tr:节点 p 的右儿子。
常量与变量
- int tot:节点个数。
- int root[i]:第 i 个线段树的根。
- int cnt:被删除过的冗余节点的个数。
- int nc[i]:第 i 个可再用的冗余节点。
- Tree a[i]:节点 i 的信息。
- int a[i].tl:节点 i 的左儿子。
- int a[i].tr:节点 i 的右儿子。
- int a[i].val:节点 i 管理的权值区间的数的个数。
函数
- Segment_Tree():初始化节点个数。
- int get_new():得到一个新节点的编号并占用此节点。
- void del(int p):删除 p 节点并清除它的信息。
- void add(int p,int x,int v,int L,int R):将权值区间为 [L,R] 的节点 p 中权值为 x 的数的个数增加 v 个。
- long long asksum(int p,int l,int r,int L,int R):求权值区间为 [L,R] 的节点 p 中权值在 [l,r] 中的数的个数。
- int askkth(int p,int k,int L,int R):求权值区间为 [L,R] 的节点 p 中第 k 小数的值。
- int merge(int x,int y):合并树根 x 和 y 并删除 y。
- void split(int p,int x,ll k):将 p 中比第 k 小数大的数都分裂到节点 x 中。
代码
#define pl a[p].tl
#define pr a[p].tr
struct Segment_Tree{
int tot,root[N],cnt,nc[N<<6];
struct Tree{
int tl,tr;
ll val;
}a[N<<6];
Segment_Tree(){
tot=0;
}
int get_new(){
return cnt?nc[cnt--]:++tot;
}
void del(int p){
nc[++cnt]=p;
a[p].tl=a[p].tr=a[p].val=0;
}
void pushup(int p){
a[p].val=a[pl].val+a[pr].val;
}
void add(int p,int x,int v,int L,int R){
if(L==R){
a[p].val+=v;
return;
}
int mid=(L+R)>>1;
if(x<=mid){
if(!pl)
pl=get_new();
add(pl,x,v,L,mid);
}
else{
if(!pr)
pr=get_new();
add(pr,x,v,mid+1,R);
}
pushup(p);
}
long long asksum(int p,int l,int r,int L,int R){
if(l<=L&&R<=r)
return a[p].val;
int mid=(L+R)>>1;
ll ans=0;
if(!pl)
pl=get_new();
if(!pr)
pr=get_new();
if(l<=mid)
ans+=asksum(pl,l,r,L,mid);
if(r>mid)
ans+=asksum(pr,l,r,mid+1,R);
return ans;
}
int askkth(int p,int k,int L,int R){
if(L==R)
return L;
int mid=(L+R)>>1;
if(a[pl].val>=k)
return askkth(pl,k,L,mid);
else
return askkth(pr,k-a[pl].val,mid+1,R);
}
int merge(int x,int y){
if(!x||!y)
return x+y;
a[x].val+=a[y].val;
a[x].tl=merge(a[x].tl,a[y].tl);
a[x].tr=merge(a[x].tr,a[y].tr);
del(y);
return x;
}
void split(int p,int x,ll k){
ll v=a[pl].val;
if(k>v){
a[x].tr=get_new();
split(pr,a[x].tr,k-v);
}
else
swap(pr,a[x].tr);
if(k<v){
a[x].tl=get_new();
split(pl,a[x].tl,k);
}
a[x].val=a[p].val-k;
a[p].val=k;
}
}tree;