4034: [HAOI2015]树上操作

4034: [HAOI2015]树上操作

链接

思路:

  树链剖分。操作:单点修改,路径查询,子树修改。

代码:

  1 #include<cstdio>
  2 #include<algorithm>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<cmath>
  6 #include<cctype>
  7 
  8 using namespace std;
  9 
 10 const int N = 100100;
 11 typedef long long LL;
 12 
 13 struct Edge{
 14     int to,nxt;
 15     Edge() {}
 16     Edge(int a,int b) {to = a,nxt = b;}
 17 }e[N<<1];
 18 int head[N],tot;
 19 LL sum[N<<2],tag[N<<2],w[N],data[N];
 20 int pos[N],siz[N],son[N],bel[N],deth[N],fa[N];
 21 int tn;
 22 
 23 inline int read() {
 24     int x = 0,f = 1;char ch = getchar();
 25     for (; !isdigit(ch); ch=getchar()) if(ch=='-') f = -1;
 26     for (; isdigit(ch); ch=getchar()) x = x*10+ch-'0';
 27     return x * f;
 28 }
 29 void add_edge(int u,int v) {
 30     e[++tot] = Edge(v,head[u]);head[u] = tot;
 31     e[++tot] = Edge(u,head[v]);head[v] = tot;
 32 }
 33 void dfs1(int u,int pa) {
 34     siz[u] = 1;
 35     deth[u] = deth[pa] + 1;
 36     fa[u] = pa;
 37     for (int i=head[u]; i; i=e[i].nxt) {
 38         int v = e[i].to;
 39         if (v==pa) continue;
 40         dfs1(v,u);
 41         siz[u] += siz[v];
 42         if (!son[u] || siz[son[u]]<siz[v]) son[u] = v;
 43     }
 44 }
 45 void dfs2(int u,int top) {
 46     bel[u] = top;
 47     pos[u] = ++tn;
 48     data[pos[u]] = w[u];
 49     if (!son[u]) return; 
 50     dfs2(son[u],top);
 51     for (int i=head[u]; i; i=e[i].nxt) {
 52         int v = e[i].to;
 53         if (v==fa[u] || v==son[u]) continue;
 54         dfs2(v,v);
 55     }
 56 }
 57 
 58 #define lson l,mid,rt<<1
 59 #define rson mid+1,r,rt<<1|1
 60 
 61 void pushup(int rt) {
 62     sum[rt] = sum[rt<<1] + sum[rt<<1|1];
 63 }
 64 void pushdown(int rt,int len) {
 65     if (tag[rt]) {
 66         sum[rt<<1] += 1ll * tag[rt] * (len-len/2);tag[rt<<1] += tag[rt];
 67         sum[rt<<1|1] += 1ll * tag[rt] * (len/2);tag[rt<<1|1] += tag[rt];
 68         tag[rt] = 0;
 69     }
 70 }
 71 void build(int l,int r,int rt) {
 72     if (l==r) {
 73         sum[rt] = data[l];
 74         return ;
 75     }
 76     int mid = (l + r) / 2;
 77     build (lson);
 78     build (rson);
 79     pushup(rt);
 80 }
 81 void update(int l,int r,int rt,int L,int R,LL x) {
 82     if (L <= l && r <= R) {
 83         sum[rt] += 1ll * (r - l + 1) * x;
 84         tag[rt] += x;
 85         return ;
 86     }
 87     pushdown(rt,r-l+1);
 88     int mid = (l + r) / 2;
 89     if (L <= mid) update(lson,L,R,x);
 90     if (R > mid)  update(rson,L,R,x);
 91     pushup(rt);
 92 }
 93 LL query(int l,int r,int rt,int L,int R) {
 94     if (L <= l && r <= R) {
 95         return sum[rt];
 96     }
 97     int mid = (l + r) / 2;
 98     LL ret = 0;
 99     pushdown(rt,r-l+1);
100     if (L <= mid) ret += query(lson,L,R);
101     if (R > mid)  ret += query(rson,L,R);
102     return ret;
103 }
104 void Ask(int x,int y) {
105     LL ans = 0;
106     while (bel[x] != bel[y]) {
107         if (deth[bel[x]] < deth[bel[y]]) swap(x,y);
108         ans += query(1,tn,1,pos[bel[x]],pos[x]);
109         x = fa[bel[x]];
110     }
111     if (deth[x] < deth[y]) swap(x,y);
112     ans += query(1,tn,1,pos[y],pos[x]);
113     printf("%lld\n",ans);
114 }
115 int main() {
116     int n = read(),m = read();
117     for (int i=1; i<=n; ++i) w[i] = read();
118     for (int i=1; i<n; ++i) {
119         int u = read(),v = read();
120         add_edge(u,v);
121     }
122     dfs1(1,0);
123     dfs2(1,1);
124     build(1,tn,1);
125     LL a;
126     while (m--) {
127         int opt = read(),x = read();
128         if (opt == 1) {
129             a = read();
130             update(1,tn,1,pos[x],pos[x],a);    
131         }
132         else if (opt==2) {
133             a = read();
134             update(1,tn,1,pos[x],pos[x]+siz[x]-1,a);
135         }
136         else Ask(x,1);
137     }
138     return 0;
139 }

 

posted @ 2018-05-20 11:10  MJT12044  阅读(201)  评论(0编辑  收藏  举报