Description
有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个操作,分为三种:
操作 1 :把某个节点 x 的点权增加 a 。
操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。
操作 3 :询问某个节点 x 到根的路径中所有点的点权和。
Input
第一行包含两个整数 N, M 。表示点数和操作数。
接下来一行 N 个整数,表示树中节点的初始权值。
接下来 N-1 行每行三个正整数 fr, to , 表示该树中存在一条边 (fr, to) 。
再接下来 M 行,每行分别表示一次操作。其中第一个数表示该操
作的种类( 1-3 ) ,之后接这个操作的参数( x 或者 x a ) 。
Output
对于每个询问操作,输出该询问的答案。答案之间用换行隔开。
Sample Input
5 5
1 2 3 4 5
1 2
1 4
2 3
2 5
3 3
1 2 1
3 5
2 1 2
3 3
1 2 3 4 5
1 2
1 4
2 3
2 5
3 3
1 2 1
3 5
2 1 2
3 3
Sample Output
6
9
13
9
13
HINT
对于 100% 的数据, N,M<=100000 ,且所有输入数据的绝对值都不
会超过 10^6 。
正解:树链剖分
解题报告:
链剖裸题。
但是我居然调试了很久!!!先是迷之RE,结果是细节问题。。。然后是迷之WA,结果是中间变量没开long long
多么痛的领悟。。。
1 //It is made by jump~ 2 #include <iostream> 3 #include <cstdlib> 4 #include <cstring> 5 #include <cstdio> 6 #include <cmath> 7 #include <algorithm> 8 #include <ctime> 9 #include <vector> 10 #include <queue> 11 #include <map> 12 #include <set> 13 #ifdef WIN32 14 #define OT "%I64d" 15 #else 16 #define OT "%lld" 17 #endif 18 using namespace std; 19 typedef long long LL; 20 const int MAXN = 100011; 21 const int MAXM = 200011; 22 int n,m; 23 int ecnt,cnt; 24 int first[MAXN],to[MAXM],next[MAXM],id[MAXN],pre[MAXN],last[MAXN],deep[MAXN],father[MAXN],size[MAXN],son[MAXN],top[MAXN]; 25 int num[MAXN]; 26 LL qx,qy; 27 int ql,qr; 28 LL ans; 29 30 struct node{ 31 LL add; 32 LL val; 33 }t[MAXN*4]; 34 35 inline int getint() 36 { 37 int w=0,q=0; 38 char c=getchar(); 39 while((c<'0' || c>'9') && c!='-') c=getchar(); 40 if (c=='-') q=1, c=getchar(); 41 while (c>='0' && c<='9') w=w*10+c-'0', c=getchar(); 42 return q ? -w : w; 43 } 44 45 inline void dfs1(int x,int fa) { 46 size[x] = 1; 47 for(int i = first[x];i;i = next[i]) { 48 int v = to[i]; 49 if(v != fa){ 50 father[v] = x; deep[v] = deep[x]+1; 51 dfs1(v,x); 52 size[x] += size[v]; if(size[v] > size[son[x]]) son[x] = v; 53 } 54 } 55 } 56 57 inline void dfs2(int x,int fa){ 58 id[x] = ++cnt; pre[cnt]=x; if(son[x]!=0) top[son[x]]=top[x],dfs2(son[x],x); 59 for(int i = first[x];i;i = next[i]){ 60 int v = to[i]; 61 if(v != fa && v != son[x]) { 62 top[v]=v; 63 dfs2(v,x); 64 } 65 } 66 last[x] = cnt; 67 } 68 69 inline void build(int root,int l,int r){ 70 if(l == r) { t[root].val = num[pre[l]]; return ; } 71 int mid = (l + r)/2; int lc = root*2,rc = lc+1; 72 build(lc,l,mid); build(rc,mid+1,r); 73 t[root].val = t[lc].val + t[rc].val; 74 } 75 76 inline void update(int root,int l,int r){ 77 if(ql <= l && qr >= r) { t[root].add += qy; t[root].val += qy*(r-l+1); } 78 else{ 79 int mid = (l + r)/2; 80 int lc = root*2,rc = lc + 1; 81 if(ql <= mid) update(lc,l,mid); if(qr > mid) update(rc,mid+1,r); 82 t[root].val = t[lc].val + t[rc].val; 83 t[root].val += t[root].add*(r-l+1); 84 } 85 } 86 87 inline void query(int root,int l,int r,LL lei){ 88 if(ql <= l && qr >= r) { 89 ans += t[root].val; 90 ans += (LL)lei*(LL)(r-l+1); 91 return ; 92 } 93 int mid = (l+r)/2; int lc = root*2,rc = lc+1; 94 if(ql <= mid) query(lc,l,mid,lei+t[root].add); if(qr > mid) query(rc,mid+1,r,lei+t[root].add); 95 } 96 97 inline void work(int x){ 98 ans=0; 99 int f1 = top[x]; 100 while(f1!=1) { 101 ql=id[f1]; qr=id[x]; 102 query(1,1,n,0); 103 x=father[f1]; f1=top[x]; 104 } 105 ql=1; qr=id[x]; query(1,1,n,0); 106 printf(OT" ",ans); 107 } 108 109 inline void solve(){ 110 n = getint(); m = getint(); 111 for(int i=1;i<=n;i++) num[i] = getint(); 112 int x,y; 113 for(int i = 1;i < n;i++) { 114 x = getint(); y = getint(); 115 next[++ecnt] = first[x]; first[x] = ecnt; to[ecnt] = y; 116 next[++ecnt] = first[y]; first[y] = ecnt; to[ecnt] = x; 117 } 118 119 deep[1]=1; dfs1(1,0); 120 top[1]=1; dfs2(1,0); 121 build(1,1,n); 122 int ljh; 123 for(int i = 1;i <= m;i++) { 124 ljh = getint(); 125 if(ljh == 1){ 126 qx = id[getint()]; qy = getint(); 127 ql=qx; qr=qx; 128 update(1,1,n); 129 } 130 else if(ljh == 2){ 131 x = getint(); qy = getint(); 132 qr = last[x]; ql = id[x]; 133 update(1,1,n); 134 } 135 else{ 136 qx=getint(); work(qx); 137 } 138 } 139 } 140 141 int main() 142 { 143 solve(); 144 return 0; 145 }