1. 程式人生 > >[BZOJ4034][HAOI2015]樹上操作(樹鏈剖分+線段樹)

[BZOJ4034][HAOI2015]樹上操作(樹鏈剖分+線段樹)

efi cst 線段樹 font size namespace void scan long long

模板題,註意long long。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define ls (x<<1)
 5 #define rs (ls|1)
 6 #define lson ls,L,mid
 7 #define rson rs,mid+1,R
 8 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
 9 #define For(i,x) for (int i=h[x],k; i; i=nxt[i])
10
typedef long long ll; 11 using namespace std; 12 13 const int N=100010; 14 int n,m,u,v,cnt,tim,op,x,k,a[N],L[N],R[N],son[N],sz[N]; 15 int dep[N],fa[N],top[N],h[N],nxt[N<<1],to[N<<1]; 16 ll sm[N<<2],tag[N<<2]; 17 void add(int u,int v){ to[++cnt]=v; nxt[cnt]=h[u]; h[u]=cnt; }
18 19 void push(int x,int L,int R){ 20 if (!tag[x]) return; 21 int mid=(L+R)>>1; 22 sm[ls]+=tag[x]*(mid-L+1); tag[ls]+=tag[x]; 23 sm[rs]+=tag[x]*(R-mid); tag[rs]+=tag[x]; 24 tag[x]=0; 25 } 26 27 void ins(int x,int L,int R,int l,int r,int k){ 28 if (L==l && r==R){ sm[x]+=1ll*k*(R-L+1
); tag[x]+=k; return; } 29 int mid=(L+R)>>1; push(x,L,R); 30 if (r<=mid) ins(lson,l,r,k); 31 else if (l>mid) ins(rson,l,r,k); 32 else ins(lson,l,mid,k),ins(rson,mid+1,r,k); 33 sm[x]=sm[ls]+sm[rs]; 34 } 35 36 ll que(int x,int L,int R,int l,int r){ 37 if (L==l && r==R) return sm[x]; 38 int mid=(L+R)>>1; push(x,L,R); 39 if (r<=mid) return que(lson,l,r); 40 else if (l>mid) return que(rson,l,r); 41 else return que(lson,l,mid)+que(rson,mid+1,r); 42 } 43 44 void dfs1(int x){ 45 sz[x]=1; dep[x]=dep[fa[x]]+1; 46 For(i,x) if ((k=to[i])!=fa[x]){ 47 fa[k]=x; dfs1(k); sz[x]+=sz[k]; 48 if (sz[k]>sz[son[x]]) son[x]=k; 49 } 50 } 51 52 void dfs2(int x,int tp){ 53 L[x]=++tim; top[x]=tp; 54 if (son[x]) dfs2(son[x],tp); 55 For(i,x) if ((k=to[i])!=fa[x] && k!=son[x]) dfs2(k,k); 56 R[x]=tim; 57 } 58 59 void solve(int x){ 60 ll res=0; 61 while (top[x]!=1) res+=que(1,1,n,L[top[x]],L[x]),x=fa[top[x]]; 62 res+=que(1,1,n,1,L[x]); printf("%lld\n",res); 63 } 64 65 int main(){ 66 freopen("bzoj4034.in","r",stdin); 67 freopen("bzoj4034.out","w",stdout); 68 scanf("%d%d",&n,&m); 69 rep(i,1,n) scanf("%d",&a[i]); 70 rep(i,2,n) scanf("%d%d",&u,&v),add(u,v),add(v,u); 71 dfs1(1); dfs2(1,1); 72 rep(i,1,n) ins(1,1,n,L[i],L[i],a[i]); 73 rep(i,1,m){ 74 scanf("%d",&op); 75 if (op==1) scanf("%d%d",&x,&k),ins(1,1,n,L[x],L[x],k); 76 if (op==2) scanf("%d%d",&x,&k),ins(1,1,n,L[x],R[x],k); 77 if (op==3) scanf("%d",&x),solve(x); 78 } 79 return 0; 80 }

[BZOJ4034][HAOI2015]樹上操作(樹鏈剖分+線段樹)