標籤:break == 方便 沒有 節點 type 一段 top can
Description
Harry Potter 新學了一種魔法:可以讓改變樹上的果子個數。滿心歡喜的他找到了一個巨大的果樹,來實驗他的新法術。
這棵果樹共有N個節點,其中節點0是根節點,每個節點u的父親記為fa[u],保證有fa[u] < u。初始時,這棵果樹上的果子都被 Dumbledore 用魔法清除掉了,所以這個果樹的每個節點上都沒有果子(即0個果子)。
不幸的是,Harry 的法術學得不到位,只能對樹上一段路徑的節點上的果子個數統一增加一定的數量。也就是說,Harry 的魔法可以這樣描述:
Add u v d
表示將點u和v之間的路徑上的所有節點的果子個數都加上d。
接下來,為了方便檢驗 Harry 的魔法是否成功,你需要告訴他在釋放魔法的過程中的一些有關果樹的資訊:
Query u
表示當前果樹中,以點u為根的子樹中,總共有多少個果子?
Input
第一行一個正整數N (1 ≤ N ≤ 100000),表示果樹的節點總數,節點以0,1,…,N ? 1標號,0一定代表根節點。
接下來N ? 1行,每行兩個整數a,b (0 ≤ a < b < N),表示a是b的父親。
接下來是一個正整數Q(1 ≤ ? ≤ 100000),表示共有Q次操作。
後面跟著Q行,每行是以下兩種中的一種:
- A u v d,表示將u到v的路徑上的所有節點的果子數加上d;0 ≤ u,v <N,0 < d < 100000
- Q u,表示詢問以u為根的子樹中的總果子數,注意是包括u本身的。
Output
對於所有的Query操作,依次輸出詢問的答案,每行一個。答案可能會超過2^32 ,但不會超過10^15 。
剛剛學樹剖練練手,一個樹剖裸題,線段樹不需要建樹.
話說省選竟然會考模板題emm
PS:數組開大,開$long ?long $,還有記得用字串讀入,不要用單個字元。
代碼
#include<cstdio>#include<cctype>#include<cstring>#include<algorithm>#define int long long#define R register#define ls o<<1#define rs o<<1|1#define N 200008using namespace std;inline void in(int &x){ int f=1;x=0;char s=getchar(); while(!isdigit(s)){if(s=='-')f=-1;s=getchar();} while(isdigit(s)){x=x*10+s-'0';s=getchar();} x*=f;}int n,head[N],tot,depth[N],size[N],son[N],dfn[N],fdfn[N],f[N];struct cod{int u,v;}edge[N<<1];int idx,m,top[N],tr[N<<2],tg[N<<2];inline void add(int x,int y){ edge[++tot].u=head[x]; edge[tot].v=y; head[x]=tot;}void dfs1(int u,int fa){ depth[u]=depth[fa]+1;size[u]=1;f[u]=fa; for(R int i=head[u];i;i=edge[i].u) { if(edge[i].v==fa)continue; dfs1(edge[i].v,u); size[u]+=size[edge[i].v]; if(son[u]==-1 or size[son[u]]<size[edge[i].v]) son[u]=edge[i].v; }}void dfs2(int u,int t){ top[u]=t;dfn[u]=++idx;fdfn[idx]=u; if(son[u]==-1)return; dfs2(son[u],t); for(R int i=head[u];i;i=edge[i].u) { if(dfn[edge[i].v])continue; dfs2(edge[i].v,edge[i].v); }}inline void down(int o,int l,int r){ if(tg[o]) { int mid=(l+r)>>1; tg[ls]+=tg[o];tg[rs]+=tg[o]; tr[ls]+=(mid-l+1)*tg[o];tr[rs]+=(r-mid)*tg[o]; tg[o]=0; }}void change(int o,int l,int r,int x,int y,int z){ if(x<=l and y>=r) { tr[o]+=(r-l+1)*z; tg[o]+=z; return; } down(o,l,r); int mid=(l+r)>>1; if(x<=mid)change(ls,l,mid,x,y,z); if(y>mid)change(rs,mid+1,r,x,y,z); tr[o]=tr[ls]+tr[rs];}int query(int o,int l,int r,int x,int y){ if(x<=l and y>=r)return tr[o]; down(o,l,r); int mid=(l+r)>>1,res=0; if(x<=mid)res+=query(ls,l,mid,x,y); if(y>mid)res+=query(rs,mid+1,r,x,y); return res;}inline void tchange(int x,int y,int z){ int fx=top[x],fy=top[y]; while(fx!=fy) { if(depth[fx]>depth[fy]) { change(1,1,idx,dfn[fx],dfn[x],z); x=f[fx]; } else { change(1,1,idx,dfn[fy],dfn[y],z); y=f[fy]; } fx=top[x],fy=top[y]; } if(dfn[x]>dfn[y])swap(x,y); change(1,1,idx,dfn[x],dfn[y],z);}signed main(){ in(n);memset(son,-1,sizeof son); for(R int i=1,x,y;i<n;i++) { in(x),in(y); x++,y++; add(x,y);add(y,x); } dfs1(1,0);dfs2(1,1); in(m); for(R int x,y,z;m;m--) { R char opt[8]; scanf("%s",opt); switch(opt[0]) { case 'A':in(x),in(y),in(z);x++;y++;tchange(x,y,z);break; case 'Q':in(x);x++;printf("%lld\n",query(1,1,n,dfn[x],dfn[x]+size[x]-1));break; } }}
【P3833】 [SHOI2012]魔法樹