[模板]树链剖分
简易版树链剖分
#include<cstdio> #include<cstring> #include<string> #include<iostream> #define WR WinterRain using namespace std; const int WR=1001000,INF=2147483647; struct SegmentTree{ int l,r,val,sum; }tree[WR]; struct Edge{ int pre,to; }edge[WR]; int n,q; int a[WR]; int head[WR],tot; int fa[WR],dpt[WR],sze[WR],son[WR]; //fa存父亲,dpt存深度,sze存子树大小,son存重儿子 int top[WR],id[WR],rnk[WR],cnt; int read(){ int s=0,n=1; char ch=getchar(); while(ch>'9'||ch<'0'){ if(ch=='-') n=-1; ch=getchar(); } while(ch>='0'&&ch<='9'){ s=(s<<1)+(s<<3)+ch-48; ch=getchar(); } return s*n; } void pushup(int k){ tree[k].sum=tree[k<<1].sum+tree[k<<1|1].sum; tree[k].val=max(tree[k<<1].val,tree[k<<1|1].val); } void build(int k,int l,int r){ tree[k].l=l,tree[k].r=r; if(l==r){ tree[k].val=tree[k].sum=a[rnk[l]]; return; } int mid=(l+r)>>1; build(k<<1,l,mid); build(k<<1|1,mid+1,r); pushup(k); } void modify(int k,int pos,int v){ if(tree[k].l==tree[k].r){ tree[k].val=tree[k].sum=v; return; } int mid=(tree[k].l+tree[k].r)>>1; if(pos<=mid) modify(k<<1,pos,v); else modify(k<<1|1,pos,v); pushup(k); } int query_sum(int k,int l,int r){ if(tree[k].l>=l&&tree[k].r<=r) return tree[k].sum; int mid=(tree[k].l+tree[k].r)>>1,res=0; if(l<=mid) res+=query_sum(k<<1,l,r); if(r>mid) res+=query_sum(k<<1|1,l,r); return res; } int query_max(int k,int l,int r){ if(tree[k].l>=l&&tree[k].r<=r) return tree[k].val; int mid=(tree[k].l+tree[k].r)>>1,res=-INF; if(l<=mid) res=max(res,query_max(k<<1,l,r)); if(r>mid) res=max(res,query_max(k<<1|1,l,r)); return res; } void add(int u,int v){ edge[++tot].pre=head[u]; edge[tot].to=v; head[u]=tot; } void dfs1(int u,int root){ fa[u]=root,dpt[u]=dpt[root]+1,sze[u]=1; for(int i=head[u];i;i=edge[i].pre){ int v=edge[i].to; if(v==root) continue; dfs1(v,u); sze[u]+=sze[v]; if(sze[v]>sze[son[u]]) son[u]=v;//找最大的子树做重儿子 } } void dfs2(int u,int tp){//tp是目前重链的顶端 top[u]=tp,id[u]=++cnt,rnk[cnt]=u;//id和rnk存储剖分时访问到的次序 if(son[u]) dfs2(son[u],tp);//有重儿子优先走重儿子 for(int i=head[u];i;i=edge[i].pre){ int v=edge[i].to; if(v!=fa[u]&&v!=son[u]) dfs2(v,v);//如果不是重儿子那么这个重链的顶端是自己 } } int path_sum(int x,int y){ int res=0; while(top[x]!=top[y]){//x,y不在一条链上 if(dpt[top[x]]<dpt[top[y]]) swap(x,y);//跳到链顶深度更大的 res+=query_sum(1,id[top[x]],id[x]);//区间查询链 x=fa[top[x]];//跳到链顶 } if(dpt[x]>dpt[y]) swap(x,y);//确定高低位置 //此时x和y肯定在一条重链上 res+=query_sum(1,id[x],id[y]); return res; } int path_max(int x,int y){ int res=-INF; while(top[x]!=top[y]){ if(dpt[top[x]]<dpt[top[y]]) swap(x,y); res=max(res,query_max(1,id[top[x]],id[x])); x=fa[top[x]]; } if(dpt[x]>dpt[y]) swap(x,y); res=max(res,query_max(1,id[x],id[y])); return res; } int main(){ n=read(); for(int i=1;i<n;i++){ int u=read(),v=read(); add(u,v);add(v,u); } for(int i=1;i<=n;i++) a[i]=read(); dfs1(1,0); dfs2(1,1); build(1,1,n); q=read(); for(int i=1;i<=q;i++){ char opt[10]; cin>>opt; int x=read(),y=read(); if(opt[1]=='H') modify(1,id[x],y); if(opt[1]=='S') printf("%d\n",path_sum(x,y)); if(opt[1]=='M') printf("%d\n",path_max(x,y)); } return 0; }
这个是正经版本的
调线段树好恶心=_=
#include<cstdio> #include<cstring> #include<string> #include<cmath> #define WR WinterRain using namespace std; const int WR=1001000; struct SegmentTree{ int l,r,val,lzy; SegmentTree(){l=r=val=lzy=0;} }tree[WR]; struct Edge{ int pre,to; }edge[WR]; int n,m,r,p; int a[WR]; int head[WR],tot; int fa[WR],dpt[WR],sze[WR],son[WR]; //fa存父亲,dpt存深度,sze存子树大小,son存重儿子 int top[WR],id[WR],rnk[WR],cnt; int read(){ int s=0,n=1; char ch=getchar(); while(ch>'9'||ch<'0'){ if(ch=='-') n=-1; ch=getchar(); } while(ch>='0'&&ch<='9'){ s=(s<<1)+(s<<3)+ch-48; ch=getchar(); } return s*n; } void pushup(int k){ tree[k].val=(tree[k<<1].val+tree[k<<1|1].val)%p; } void pushdown(int k){ tree[k<<1].lzy+=tree[k].lzy; tree[k<<1|1].lzy+=tree[k].lzy; tree[k<<1].val+=tree[k].lzy*(tree[k<<1].r-tree[k<<1].l+1); tree[k<<1|1].val+=tree[k].lzy*(tree[k<<1|1].r-tree[k<<1|1].l+1); tree[k<<1].val%=p; tree[k<<1|1].val%=p; tree[k].lzy=0; } void build(int k,int l,int r){ tree[k].l=l,tree[k].r=r; if(l==r){ tree[k].val=a[rnk[l]]%p; return; } int mid=(l+r)>>1; build(k<<1,l,mid); build(k<<1|1,mid+1,r); pushup(k); } void modify(int k,int st,int ed,int v){ if(tree[k].l>=st&&tree[k].r<=ed){ tree[k].lzy+=v; tree[k].val+=(tree[k].r-tree[k].l+1)*v; tree[k].val%=p; return; } if(tree[k].lzy) pushdown(k); int mid=(tree[k].l+tree[k].r)>>1; if(st<=mid) modify(k<<1,st,ed,v); if(ed>mid) modify(k<<1|1,st,ed,v); pushup(k); } int query(int k,int l,int r){ if(tree[k].l>=l&&tree[k].r<=r){ return tree[k].val%p; } if(tree[k].lzy) pushdown(k); int mid=(tree[k].l+tree[k].r)>>1,res=0; if(l<=mid) res+=query(k<<1,l,r); if(r>mid) res+=query(k<<1|1,l,r); return res%p; } void add(int u,int v){ edge[++tot].pre=head[u]; edge[tot].to=v; head[u]=tot; } void dfs1(int u,int root){ fa[u]=root,dpt[u]=dpt[root]+1,sze[u]=1; for(int i=head[u];i;i=edge[i].pre){ int v=edge[i].to; if(v==root) continue; dfs1(v,u); sze[u]+=sze[v]; if(sze[v]>sze[son[u]]) son[u]=v; } } void dfs2(int u,int tp){ top[u]=tp,id[u]=++cnt,rnk[cnt]=u; if(son[u]) dfs2(son[u],tp); for(int i=head[u];i;i=edge[i].pre){ int v=edge[i].to; if(v!=fa[u]&&v!=son[u]) dfs2(v,v); } } int path_sum(int x,int y){ int res=0; while(top[x]!=top[y]){ if(dpt[top[x]]<dpt[top[y]]) swap(x,y); res+=query(1,id[top[x]],id[x]); res%=p; x=fa[top[x]]; } if(dpt[x]>dpt[y]) swap(x,y); res+=query(1,id[x],id[y]); return res%p; } void path_modify(int x,int y,int v){ v%=p; while(top[x]!=top[y]){ if(dpt[top[x]]<dpt[top[y]]) swap(x,y); modify(1,id[top[x]],id[x],v); x=fa[top[x]]; } if(dpt[x]>dpt[y]) swap(x,y); modify(1,id[x],id[y],v); } int main(){ freopen("test.in","r",stdin); freopen("test.out","w",stdout); n=read(),m=read(),r=read(),p=read(); for(int i=1;i<=n;i++) a[i]=read(); for(int i=1;i<n;i++){ int u=read(),v=read(); add(u,v);add(v,u); } dfs1(r,0); dfs2(r,r); build(1,1,n); for(int i=1;i<=m;i++){ int opt=read(); if(opt==1){ int x=read(),y=read(),z=read(); path_modify(x,y,z%p); } if(opt==2){ int x=read(),y=read(); printf("%d\n",path_sum(x,y)%p); } if(opt==3){ int x=read(),z=read(); modify(1,id[x],id[x]+sze[x]-1,z%p); } if(opt==4){ int x=read(); printf("%d\n",query(1,id[x],id[x]+sze[x]-1)%p); } } return 0; }
本文来自博客园,作者:冬天丶的雨,转载请注明原文链接:https://www.cnblogs.com/WintersRain/p/16285139.html
为了一切不改变的理想,为了改变不理想的一切