HDU 5405 (树链剖分+线段树)

Problem Sometimes Naive

题目大意

  给你一棵n个节点的树,有点权。

  要求支持两种操作:

    操作1:更改某个节点的权值。

    操作2:给定u,v, 求 Σw[i][j]   i , j 为任意两点且i到j的路径与u到v的路径相交。

解题分析

  容易发现对于一个询问,答案为总点权和的平方 减去 去掉u--v这条链后各个子树的点权和的平方的和。 

  开两棵线段树,tag1记录点权和,tag2记录某点的所有轻链子树的点权和的平方的和。

  每次沿着重链往上走时,直接加上这条重链的所有点的tag2和,若有重儿子则直接用tag1计算。由于该条重链必定为其父亲的轻链,故为防止计算重复,还需减去该重链所有点的tag1平方和。

  最后爬到同一颗重链后,还需计算重链上方所有点的贡献。

参考程序

  1 #include <map>
  2 #include <set>
  3 #include <stack>
  4 #include <queue>
  5 #include <cmath>
  6 #include <ctime>
  7 #include <string>
  8 #include <vector>
  9 #include <cstdio>
 10 #include <cstdlib>
 11 #include <cstring>
 12 #include <cassert>
 13 #include <iostream>
 14 #include <algorithm>
 15 #pragma comment(linker,"/STACK:102400000,102400000")
 16 using namespace std;
 17 
 18 #define V 100008             
 19 #define E 200008   
 20 #define LL long long
 21 #define lson l,m,rt<<1
 22 #define rson m+1,r,rt<<1|1 
 23 #define clr(x,v) memset(x,v,sizeof(x));
 24 #define rep(x,y,z) for (int x=y;x<=z;x++)
 25 #define repd(x,y,z) for (int x=y;x>=z;x--)
 26 const int mo  = 1000000007;
 27 const int inf = 0x3f3f3f3f;
 28 const int INF = 2000000000;
 29 /**************************************************************************/ 
 30 int n,m,tot;
 31 int val[V];
 32 int size[V],fa[V],w[V],top[V],rk[V],dep[V],son[V];
 33 
 34 struct line{
 35     int u,v,nt;
 36     line(int u=0,int v=0,int nt=0):u(u),v(v),nt(nt){}
 37 }eg[E];
 38 int lt[V],sum;
 39 
 40 void add(int u,int v){
 41     eg[++sum]=line(u,v,lt[u]); lt[u]=sum;    
 42 }
 43 
 44 struct Segment_Tree{
 45     LL sum[V<<2];
 46     void clear(){
 47         clr(sum,0);
 48     }
 49     void pushup(int rt){
 50         sum[rt] = (sum[rt<<1] + sum[rt<<1|1]) % mo;
 51     }
 52     void update(int x,int val,int l,int r,int rt){
 53         if (l==r){
 54             sum[rt] += val;
 55             sum[rt] = sum[rt] % mo;
 56             return;
 57         }
 58         int m=(l+r)>>1;
 59         if (x <= m) update(x,val,lson);
 60         if (m <  x) update(x,val,rson);
 61         pushup(rt);
 62     }
 63     LL query(int L,int R,int l,int r,int rt){
 64         if (L<=l && r<=R){
 65             return sum[rt];
 66         }
 67         int m=(l+r)>>1;
 68         LL res=0;
 69         if (L <= m) res += query(L,R,lson);
 70         if (m <  R) res += query(L,R,rson);
 71         res = res % mo;
 72         return res;
 73     }
 74 
 75 }Ts,Td;
 76 void init(){
 77     clr(lt,0); sum=1; tot=0;
 78     Ts.clear();
 79     Td.clear();
 80 }
 81 void dfs_1(int u){
 82     dep[u]=dep[fa[u]]+1; size[u]=1; son[u]=0; 
 83     for (int i=lt[u];i;i=eg[i].nt){
 84         int v=eg[i].v;
 85         if (v==fa[u]) continue;
 86         fa[v]=u;
 87         dfs_1(v);
 88         if (size[v]>size[son[u]]) son[u]=v;
 89         size[u]+=size[v];
 90     }
 91 }
 92 
 93 void dfs_2(int u,int tp){
 94     top[u]=tp; w[u]=++tot; rk[tot]=u;;
 95     if (son[u]) dfs_2(son[u],tp);
 96     for (int i=lt[u];i;i=eg[i].nt){
 97         int v=eg[i].v;
 98         if (v==fa[u]||v==son[u]) continue;
 99         dfs_2(v,v);
100     }
101 }
102 
103 int sqr(int x){return 1ll*x*x %mo;}
104 void update(int x,int v){
105     int u=top[x];
106     while (fa[u]){
107         LL sum=Ts.query(w[u],w[u]+size[u]-1,1,n,1);
108         Td.update(w[fa[u]],(sqr(val[x]-v)-sum*2*(val[x]-v) % mo)%mo,1,n,1);
109         u=top[fa[u]];
110     }
111     Ts.update(w[x],v-val[x],1,n,1);
112     val[x]=v;
113 }
114 LL query(int x,int y){
115     LL res=0;
116     while (top[x]!=top[y]){
117         if (dep[top[x]]<dep[top[y]]) swap(x,y);
118         res += Td.query(w[top[x]],w[x],1,n,1);
119         res = res % mo;
120        
121         if (son[x]){
122             LL sum=Ts.query(w[son[x]],w[son[x]]+size[son[x]]-1,1,n,1);
123             res = res + sum*sum;
124             res = res % mo;
125         }
126         LL sum=Ts.query(w[top[x]],w[top[x]]+size[top[x]]-1,1,n,1);
127         
128         res = res - sum*sum;
129         res = res % mo;
130         while (res<0) res+=mo;
131         x=fa[top[x]];
132     }
133     if (dep[x]>dep[y]) swap(x,y);
134     res += Td.query(w[x],w[y],1,n,1);
135     res = res % mo;
136     if (son[y]){
137         LL sum=Ts.query(w[son[y]],w[son[y]]+size[son[y]]-1,1,n,1);
138         res = res + sum*sum;
139         res = res % mo;
140     }
141     if (fa[x]){
142         LL sum=Ts.query(1,n,1,n,1)-Ts.query(w[x],w[x]+size[x]-1,1,n,1);
143         res = res + sum*sum;
144         res = res % mo;
145     }
146     return res;
147 }
148 
149 int main(){
150     while (~scanf("%d %d",&n,&m)){
151         init();
152         rep(i,1,n) scanf("%d",&val[i]);
153         rep(i,2,n){
154             int u,v;
155             scanf("%d %d",&u,&v);
156             add(u,v); add(v,u);
157         }
158         dfs_1(1);
159         dfs_2(1,1);
160         rep(i,1,n){
161             int k=val[i];
162             val[i]=0;
163             update(i,k);
164         }
165         while (m--){
166             int x,u,v;
167             scanf("%d %d %d",&x,&u,&v);
168             if (x==1) update(u,v);
169                 else {
170                     LL sum=Ts.query(w[1],w[1]+size[1]-1,1,n,1);
171                     sum = sum * sum;
172                     sum = sum - query(u,v);
173                     sum = sum % mo;
174                     while (sum<0) sum+=mo;
175                     printf("%lld
",sum);
176                 }
177         }
178     }
179 }
View Code

  

原文地址:https://www.cnblogs.com/rpSebastian/p/5782489.html