BZOJ4034 T2

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

Sample Output

6
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"\n",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 }

 

本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ 转载请注明出处,侵权必究,保留最终解释权!
posted @ 2016-06-25 15:56  ljh_2000  阅读(387)  评论(0编辑  收藏  举报