BZOJ1036: [ZJOI2008]树的统计Count

Description

  一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成
一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 I
II. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身

Input

  输入的第一行为一个整数n,表示节点的个数。接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有
一条边相连。接下来n行,每行一个整数,第i行的整数wi表示节点i的权值。接下来1行,为一个整数q,表示操作
的总数。接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。 
对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。

Output

  对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。

Sample Input

4
1 2
2 3
4 1
4 2 1 3
12
QMAX 3 4
QMAX 3 3
QMAX 3 2
QMAX 2 3
QSUM 3 4
QSUM 2 1
CHANGE 1 5
QMAX 3 4
CHANGE 3 6
QMAX 3 4
QMAX 2 4
QSUM 3 4

Sample Output

4
1
2
2
10
6
5
6
5
16

HINT

 

Source

 

 树剖的模版题
  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<algorithm>
  4 #include<cstring>
  5 #define MAXN 30005
  6 using namespace std;
  7 int fa[MAXN],dep[MAXN],size[MAXN],gs[MAXN];
  8 int top[MAXN],tree[MAXN],pre[MAXN],tot;
  9 int first[MAXN],nxt[MAXN<<1],to[MAXN<<1],cnt;
 10 int n;
 11 int dat1[MAXN<<2],dat2[MAXN<<2],A[MAXN];
 12 int read(){
 13     int x=0,f=1;char ch=getchar();
 14     while(ch<'0'||ch>'9'){if('-'==ch)f=-1;ch=getchar();}
 15     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
 16     return x*f;
 17 }
 18 void add(int x,int y){
 19     nxt[++cnt]=first[x];first[x]=cnt;to[cnt]=y;
 20     nxt[++cnt]=first[y];first[y]=cnt;to[cnt]=x;
 21 }
 22 void dfs1(int x){
 23     size[x]=1;
 24     for(int e=first[x];e;e=nxt[e]){
 25         int y=to[e];
 26         if(y==fa[x]){
 27             continue;
 28         }
 29         fa[y]=x;
 30         dep[y]=dep[x]+1;
 31         dfs1(y);
 32         size[x]+=size[y];
 33         if(size[y]>size[gs[x]]){
 34             gs[x]=y;
 35         }
 36     }
 37 }
 38 void dfs2(int x,int t){
 39     top[x]=t;
 40     tree[x]=(++tot);
 41     pre[tot]=x;
 42     if(!gs[x]){
 43         return;
 44     }
 45     dfs2(gs[x],t);
 46     for(int e=first[x];e;e=nxt[e]){
 47         int y=to[e];
 48         if(y==fa[x]||y==gs[x]){
 49             continue;
 50         }
 51         dfs2(y,y);
 52     }
 53 }
 54 void pushup(int k){
 55     dat1[k]=dat1[k<<1]+dat1[k<<1|1];
 56     dat2[k]=max(dat2[k<<1],dat2[k<<1|1]);
 57 }
 58 void build(int k,int L,int R){
 59     if(L+1==R){
 60         dat1[k]=dat2[k]=A[pre[L]];
 61         return;
 62     }
 63     build(k<<1,L,(L+R)>>1);
 64     build(k<<1|1,(L+R)>>1,R);
 65     pushup(k);
 66 }
 67 void init(){
 68     n=read();
 69     for(int i=1;i<n;i++){
 70         int x=read(),y=read();
 71         add(x,y);
 72     }
 73     for(int i=1;i<=n;i++){
 74         A[i]=read();
 75     }
 76     dfs1(1);
 77     dfs2(1,1);
 78     build(1,1,n+1);
 79 }
 80 void add(int a,int k,int L,int R,int x){
 81     if(L+1==R){
 82         dat1[k]=dat2[k]=x;
 83         return; 
 84     }
 85     int mid=((L+R)>>1);
 86     if(a<mid){
 87         add(a,k<<1,L,mid,x);
 88     }
 89     else{
 90         add(a,k<<1|1,mid,R,x);
 91     }
 92     pushup(k);
 93 }
 94 int query_sum(int a,int b,int k,int L,int R){
 95     if(b<=L||R<=a){
 96         return 0;
 97     }
 98     else if(a<=L&&R<=b){
 99         return dat1[k];
100     }    
101     else{
102         int lc=query_sum(a,b,k<<1,L,(L+R)>>1);
103         int rc=query_sum(a,b,k<<1|1,(L+R)>>1,R);
104         return (lc+rc);
105     }
106 }
107 int query_max(int a,int b,int k,int L,int R){
108     if(b<=L||R<=a){
109         return -1000000;
110     }
111     else if(a<=L&&R<=b){
112         return dat2[k];
113     }    
114     else{
115         int lc=query_max(a,b,k<<1,L,(L+R)>>1);
116         int rc=query_max(a,b,k<<1|1,(L+R)>>1,R);
117         return max(lc,rc);
118     }
119 }
120 int tree_ask_sum(int x,int y){
121     int f1=top[x],f2=top[y];
122     if(dep[f1]<dep[f2]){
123         swap(f1,f2),swap(x,y);
124     }
125     int ret=0;
126     while(f1!=f2){
127         ret+=query_sum(tree[f1],tree[x]+1,1,1,n+1);
128         x=fa[f1],f1=top[x];
129         if(dep[f1]<dep[f2]){
130             swap(f1,f2),swap(x,y);
131         }
132     }
133     if(dep[x]>dep[y]){
134         swap(x,y);
135     }
136     ret+=query_sum(tree[x],tree[y]+1,1,1,n+1);
137     return ret;
138 }
139 int tree_ask_max(int x,int y){
140     int f1=top[x],f2=top[y];
141     if(dep[f1]<dep[f2]){
142         swap(f1,f2),swap(x,y);
143     }
144     int ret=-1000000;
145     while(f1!=f2){
146         ret=max(ret,query_max(tree[f1],tree[x]+1,1,1,n+1));
147         x=fa[f1],f1=top[x];
148         if(dep[f1]<dep[f2]){
149             swap(f1,f2),swap(x,y);
150         }
151     }
152     if(dep[x]>dep[y]){
153         swap(x,y);
154     }
155     ret=max(ret,query_max(tree[x],tree[y]+1,1,1,n+1));
156     return ret;
157 }
158 void solve(){
159     int T=read();
160     for(int i=1;i<=T;i++){
161         char ch[10];
162         scanf("%s",ch);
163         int x=read(),y=read();
164         if('M'==ch[1]){
165             printf("%d\n",tree_ask_max(x,y));
166         }
167         else if('S'==ch[1]){
168             printf("%d\n",tree_ask_sum(x,y));
169         }
170         else{
171             add(tree[x],1,1,n+1,y);
172         }
173     }
174 }
175 int main()
176 {
177 //    freopen("data.in","r",stdin);
178     init();
179     solve();
180     return 0;
181 }

 

posted @ 2017-11-11 22:24  white_hat_hacker  阅读(154)  评论(0编辑  收藏  举报