树链剖分的代码实在是长,少有的几次代码行数过百了
线段树 在图论里面的应用
线段树是处理区间问题的
在图论的树里面的应用就是通过重链的方式dfs编号,形成一段连续的区间,就可以用线段树来处理了;
能做到的事情为
如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作:
操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节点的值都加上z
操作2: 格式: 2 x y 表示求树从x到y结点最短路径上所有节点的值之和
操作3: 格式: 3 x z 表示将以x为根节点的子树内所有节点值都加上z
操作4: 格式: 4 x 表示求以x为根节点的子树内所有节点值之和
#include
#include
#include
using namespace std;
const int maxn=1e5+7;
struct node{
int l,r,sum,lazy;
}seg[maxn<<2];
int h[maxn],e[maxn<<1],ne[maxn<<1],idx;
int w[maxn],id[maxn],cnt,w2[maxn],deep[maxn],fa[maxn],siz[maxn],son[maxn],top[maxn];
int n,m,root,mod;
void add(int a,int b){
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void dfs1(int x,int f){
deep[x]=deep[f]+1,fa[x]=f,siz[x]=1;
int max_son=-1;
for(int i=h[x];~i;i=ne[i]){
int j=e[i];if(j==f)continue;
dfs1(j,x);siz[x]+=siz[j];
if(siz[j]>max_son)max_son=siz[j],son[x]=j;
}
}
void dfs2(int x,int topf){
id[x]=++cnt,w2[cnt]=w[x],top[x]=topf;
if(!son[x])return;
dfs2(son[x],topf);
for(int i=h[x];~i;i=ne[i]){
int j=e[i];if(j==son[x]||j==fa[x])continue;
dfs2(j,j);
}
}
void push_down(int p){
if(!seg[p].lazy)return;
int l=seg[p].l,r=seg[p].r,mid=l+r>>1;
seg[p<<1].lazy+=seg[p].lazy,seg[p<<1].sum+=seg[p].lazy*(mid-l+1);
seg[p<<1|1].lazy+=seg[p].lazy,seg[p<<1|1].sum+=seg[p].lazy*(r-mid);
seg[p].lazy=0;
}
void build(int p,int L,int R){
seg[p].l=L,seg[p].r=R;
if(L==R){seg[p].sum=w2[L]%mod;return;}
int mid=L+R>>1;
build(p<<1,L,mid);build(p<<1|1,mid+1,R);
seg[p].sum=(seg[p<<1].sum+seg[p<<1|1].sum)%mod;
}
int query(int p,int L,int R){
int l=seg[p].l,r=seg[p].r,mid=l+r>>1;
if(L<=l&&r<=R)return seg[p].sum;
int ans=0;push_down(p);
if(L<=mid)ans+=query(p<<1,L,R);
if(mid+1<=R)ans+=query(p<<1|1,L,R);
return ans%mod;
}
void change(int p,int L,int R,int d){
int l=seg[p].l,r=seg[p].r,mid=l+r>>1;
if(L<=l&&r<=R){seg[p].sum+=d*(r-l+1);seg[p].lazy+=d;return;}
push_down(p);
if(L<=mid)change(p<<1,L,R,d);
if(mid+1<=R)change(p<<1|1,L,R,d);
seg[p].sum=(seg[p<<1].sum+seg[p<<1|1].sum)%mod;
}
int q_range(int x,int y){
int ans=0;
while(top[x]!=top[y]){
if(deep[top[x]]deep[y])swap(x,y);
ans+=query(1,id[x],id[y]);
return ans;
}
void add_range(int x,int y,int d){
while(top[x]!=top[y]){
if(deep[top[x]]deep[y])swap(x,y);
change(1,id[x],id[y],d);
}
int main()
{
scanf("%d%d%d%d",&n,&m,&root,&mod);
for(int i=1;i<=n;i++)scanf("%d",&w[i]);
memset(h,-1,sizeof h);int a,b,op,z;
for(int i=1;i