维护节点:
inline void uphold(int node)
{
tr[node]=tr[node<<1]+tr[node<<1|1];//线段树求区间和
} 普通线段树
建树:
int a[N];
int tr[N<<2];//开四倍
void build(int node,int l,int r)
{
if(l==r)
{
tr[node]=a[l];
return;
}
int mid=(l+r)>>1;// (>>1) <=> (/2)
build(node<<1, l, mid);
build(node<<1|1, mid+1, r);
uphold(node);//根据左右子树情况维护当前节点
} 单点修改:
void pmodify(int node,int l,int r,int x,int val)
{
if(l==r)
{
tr[node]=val;
return;
}
int mid=(l+r)>>1;
if(x<=mid)
pmodify(node<<1, l, mid,x,val);
else pmodify(node<<1|1, mid+1, r,x,val);
uphold(node);
} 下放
:
int tag[N];
void lazy(int node,int l,int r)
{
if(tag[node])
{
int mid=(l+r)>>1;
tag[node<<1]+=tag[node];
tag[node<<1|1]+=tag[node];
tr[node<<1]+=tag[node]*(mid-l+1);
tr[node<<1|1]+=tag[node]*(r-mid);
tag[node]=0;
}
} 区间修改:
void smodify(int node,int l,int r,int L,int R,int val)
{
if(L<=l&&r<=R)
{
tr[node]+=val*(r-l+1);
tag[node]+=val;
return;
}
lazy(node,l,r);
int mid=(l+r)>>1;
int ret=0;
if(L<=mid)smodify(node<<1,l,mid,L,R,val);
if(R>=mid+1)smodify(node<<1|1,mid+1,r,L,R,val);
uphold(node);
} 区间查询:
int query(int node,int l,int r,int L,int R)
{
if(l>=L&&r<=R)
return tr[node];
lazy(node,l,r);
int mid=(l+r)>>1;
if(mid>=L)ret+=query(node<<1,l,mid,L,R);
if(mid+1<=R)ret+=query(node<<1|1,mid+1,r,L,R);
return ret;
} 模板:
#include<iostream>
#include<algorithm>
using namespace std;
const int N=500010,M=100010;
int n,m;
int a[N];
int tr[N<<2];
void uphold(int node)
{
tr[node]=tr[node<<1]+tr[node<<1|1];
}
void build(int node,int l,int r)
{
if(l==r)
{
tr[node]=a[l];
return;
}
int mid=(l+r)>>1;
build(node<<1, l, mid);
build(node<<1|1, mid+1, r);
uphold(node);
}
void pmodify(int node,int l,int r,int x,int val)
{
if(l==r)
{
tr[node]=val;
return;
}
int mid=(l+r)>>1;
if(x<=mid)
pmodify(node<<1, l, mid,x,val);
else pmodify(node<<1|1, mid+1, r,x,val);
uphold(node);
}
int tag[N];
void lazy(int node,int l,int r)
{
if(tag[node])
{
int mid=(l+r)>>1;
tag[node<<1]+=tag[node];
tag[node<<1|1]+=tag[node];
tr[node<<1]+=tag[node]*(mid-l+1);
tr[node<<1|1]+=tag[node]*(r-mid);
tag[node]=0;
}
}
int query(int node,int l,int r,int L,int R)
{
if(l>=L&&r<=R)
return tr[node];
lazy(node,l,r);
int mid=(l+r)>>1;
if(mid>=L)ret+=query(node<<1,l,mid,L,R);
if(mid+1<=R)ret+=query(node<<1|1,mid+1,r,L,R);
return ret;
}
void smodify(int node,int l,int r,int L,int R,int val)
{
if(L<=l&&r<=R)
{
tr[node]+=val*(r-l+1);
tag[node]+=val;
return;
}
lazy(node,l,r);
int mid=(l+r)>>1;
int ret=0;
if(L<=mid)smodify(node<<1,l,mid,L,R,val);
if(R>=mid+1)smodify(node<<1|1,mid+1,r,L,R,val);
uphold(node);
}
int main()
{
/*Code*/
return 0;
} 权值线段树
添加节点
void update(int node,int l,int r,int val)
{
if(l==r)
{
tr[node]++;
return;
}
int mid=(l+r)>>1;
if(val<=mid)
update(node<<1,l,mid,val);
else update(node<<1|1,mid+1,r,val);
uphold(node);
} 查询一段区间数出现次数总和
int find(int node,int l,int r,int L,int R)
{
if(L<=l&&r<=R)
return tr[node];
int mid=(l+r)>>1;
int ret=0;
if(L<=mid)
ret+=find(node<<1,l,mid,L,R);
if(R>=mid+1)
ret+=find(node<<1|1,mid+1,r,L,R);
return ret;
} 查询比x大的数有多少个(函数查大于等于)
int bquery(int node,int l,int r,int x)
{
if(l==r)
return tr[node];
int mid=(l+r)>>1;
if(x>mid)return bquery(node<<1|1,mid+1,r,x);
else return tr[node<<1|1]+bquery(node<<1,l,mid,x);
}
bquery(1,1,n,x+1); 查询第k大的数值(不去重)
int fquery(int node,int l,int r,int k)
{
if(l==r)return l;
int mid=(l+r)>>1;
if(k<=tr[node<<1])
return fquery(node<<1,l,mid,k);
else return fquery(node<<1,mid+1,r,k-tr[node<<1]);
} 模板
#include<iostream>
using namespace std;
int tr[1000];
inline void uphold(int node)
{
tr[node]=tr[node<<1]+tr[node<<1|1];//Ïß¶ÎÊ÷ÇóÇø¼äºÍ
}
void update(int node,int l,int r,int val)
{
if(l==r)
{
tr[node]++;
return;
}
int mid=(l+r)>>1;
if(val<=mid)
update(node<<1,l,mid,val);
else update(node<<1|1,mid+1,r,val);
uphold(node);
}
int find(int node,int l,int r,int L,int R)
{
if(L<=l&&r<=R)
return tr[node];
int mid=(l+r)>>1;
int ret=0;
if(L<=mid)
ret+=find(node<<1,l,mid,L,R);
if(R>=mid+1)
ret+=find(node<<1|1,mid+1,r,L,R);
return ret;
}
int bquery(int node,int l,int r,int x)
{
if(l==r)
return tr[node];
int mid=(l+r)>>1;
if(x>mid)return bquery(node<<1|1,mid+1,r,x);
else return tr[node<<1|1]+bquery(node<<1,l,mid,x);
}
int fquery(int node,int l,int r,int k)
{
if(l==r)return l;
int mid=(l+r)>>1;
if(k<=tr[node<<1])
return fquery(node<<1,l,mid,k);
else return fquery(node<<1,mid+1,r,k-tr[node<<1]);
}
int main()
{
/*Code*/
return 0;
}