【bzoj3589】动态树 树链剖分+树链的并
题解:
树链剖分是显然的
问题在于求树链的并
比较简单的方法是
用线段树打标记覆盖,查询标记区间大小
Qlog^2n
代码:
#include <bits/stdc++.h> using namespace std; #define IL inline #define rint register int #define rep(i,h,t) for (rint i=h;i<=t;i++) #define dep(i,t,h) for (rint i=t;i>=h;i--) const int N=3e5; const int N1=N*4; const int INF=1e9; int n,l,cnt,dfn[N],size[N],fa[N],top[N],son[N],head[N],dep[N]; struct re{ int a,b; }a[N*2]; void arr(int x,int y) { a[++l].a=head[x]; a[l].b=y; head[x]=l; } void dfs(int x,int y) { fa[x]=y; size[x]=1; int u=head[x]; dep[x]=dep[y]+1; while (u) { int v=a[u].b; if (v!=y) { dfs(v,x); if (size[v]>size[son[x]]) son[x]=v; size[x]+=size[v]; } u=a[u].a; } } void dfs2(int x,int y) { dfn[x]=++cnt; top[x]=y; if (!son[x]) return; dfs2(son[x],y); int u=head[x]; while (u) { int v=a[u].b; if (v!=fa[x]&&v!=son[x]) dfs2(v,v); u=a[u].a; } } struct sgt{ int sum[N1],sum1[N1],lazy[N1],lazy1[N1]; #define mid ((h+t)/2) IL void clear() { lazy1[1]=-1; sum1[1]=0; } IL int query() { return sum1[1]; } IL void down(int x,int h,int t) { if (lazy[x]) { sum[x*2]+=(mid-h+1)*lazy[x]; sum[x*2+1]+=(t-mid)*lazy[x]; lazy[x*2]+=lazy[x]; lazy[x*2+1]+=lazy[x]; lazy[x]=0; } if (lazy1[x]) { lazy1[x*2]=lazy1[x*2+1]=lazy1[x]; if (lazy1[x]==1) sum1[x*2]=sum[x*2],sum1[x*2+1]=sum[x*2+1]; else sum1[x*2]=sum1[x*2+1]=0; lazy1[x]=0; } } IL void updata(int x) { sum[x]=sum[x*2]+sum[x*2+1]; sum1[x]=sum1[x*2]+sum1[x*2+1]; } void change(int x,int h,int t,int h1,int t1,int k) { if (h1<=h&&t<=t1) { lazy[x]+=k; sum[x]+=(t-h+1)*k; return; } down(x,h,t); if (h1<=mid) change(x*2,h,mid,h1,t1,k); if (mid<t1) change(x*2+1,mid+1,t,h1,t1,k); updata(x); } void push(int x,int h,int t,int h1,int t1) { if (h1<=h&&t<=t1) { lazy1[x]=1; sum1[x]=sum[x]; return; } down(x,h,t); if (h1<=mid) push(x*2,h,mid,h1,t1); if (mid<t1) push(x*2+1,mid+1,t,h1,t1); updata(x); } }S; void change(int x,int y) { int kk=dfn[x]; S.change(1,1,n,kk,kk+size[x]-1,y); } void query(int x,int y) { int f1=top[x],f2=top[y]; while (top[x]!=top[y]) { if (dep[f1]<dep[f2]) swap(f1,f2),swap(x,y); S.push(1,1,n,dfn[f1],dfn[x]); x=fa[f1]; f1=top[x]; } if (dep[x]<dep[y]) swap(x,y); S.push(1,1,n,dfn[y],dfn[x]); } int main() { freopen("1.in","r",stdin); freopen("1.out","w",stdout); ios::sync_with_stdio(false); cin>>n; rep(i,1,n-1) { int x,y; cin>>x>>y; arr(x,y); arr(y,x); } dfs(1,0); dfs2(1,1); int m; cin>>m; rep(i,1,m) { int kk,x,y,p; cin>>kk; if (!kk) { cin>>x>>y; change(x,y); } else { cin>>p; rep(j,1,p) { cin>>x>>y; query(x,y); } int ans=S.query(); if (ans<0) ans+=1<<31; cout<<ans<<endl; S.clear(); } } return 0; }