1036: [ZJOI2008]树的统计Count

Description

一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 III. 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
 
裸树链剖分。。。写的时候要注意点权有负的情况,边是两倍,因为是双向边。。。
对于树链剖分实际上就是一个把一棵树变成很多条链,这样子在树上的操作就变成了区间操作,这样再依托于数据结构就好了。。。
不过对于一棵树,如何划分也是有标准的。。。对于一颗树我们设第i个点的儿子节点数为son[i],那么对于一个节点在它的所有儿子x中son[x]最大的称为重点。。。如果一条链上的所有点都是重点,那么这条链就是重链。。。这样一来一棵树就变成了一条一条的链,这样就可以变为区间操作了。。。
我们可以通过两次dfs来找到重链。。。第一次dfs可以求出一个节点的子节点个数,它的父节点。。。
void dfs(int x){
    s[x]=1;
    for(int y=son[x]=0,i=head[x];i;i=e[i].next){
        if(dep[y=e[i].go]==0){
            dep[y]=dep[x]+1;fa[y]=x;dfs(y);
            s[x]+=s[y];if(s[y]>s[son[x]])son[x]=y;
        }
    }
}
void dfs2(int x,int chain){
    p[x]=++cnt;top[x]=chain;a[p[x]]=w[x];
    if(son[x])dfs2(son[x],chain);
    for(int i=head[x],y=e[i].go;i;i=e[i].next,y=e[i].go)
        if(y!=fa[x]&&y!=son[x])dfs2(y,y);
}

  

然后第二次dfs来求出重链,然后用dfs的顺序对每个点重新编号,然后建立数据结构即可。。。
  4 #include<iostream>
  5 #include<cstdlib>
  6 #include<cmath>
  7 #include<cstring>
  8 #include<cstdio>
  9 #include<algorithm>
 10 #include<string>
 11 #include<map>
 12 #include<queue>
 13 #include<vector>
 14 #include<set>
 15 #define inf 1000000000
 16 #define maxn 30005
 17 #define maxm 30005*2
 18 #define eps 1e-10
 19 #define ll long long
 20 #define for0(i,n) for(int i=0;i<=(n);i++)
 21 #define for1(i,n) for(int i=1;i<=(n);i++)
 22 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
 23 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
 24 #define for4(i,x) for(int i=head[x],y=e[i].go;i;i=e[i].next,y=e[i].go)
 25 using namespace std;
 26 int read()
 27 {
 28     int x=0,f=1;char ch=getchar();
 29     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 30     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
 31     return x*f;
 32 }
 33 struct tree{
 34     int l,r,sum,mx;
 35 }f[maxn*4];
 36 struct edge{
 37     int go,next;
 38 }e[maxm];
 39 int head[maxn],w[maxn],top[maxn],fa[maxn],p[maxn],son[maxn],s[maxn],dep[maxn],a[maxn],tot,cnt;
 40 void pushup(int i){
 41     f[i].sum=(f[i*2+1].sum+f[i*2].sum);
 42     f[i].mx=max(f[i*2+1].mx,f[i*2].mx);
 43 }
 44  
 45 void build(int i,int left,int right){
 46     int mid=(left+right)/2;
 47     f[i].mx=-inf;f[i].l=left;f[i].r=right;
 48     if(left==right){
 49         f[i].sum=a[left];
 50         f[i].mx=a[left];
 51         return;
 52     }
 53     build(i*2,left,mid);
 54     build(i*2+1,mid+1,right);
 55     pushup(i);
 56 }
 57  
 58 void change(int i,int goal,int v){
 59     int mid=(f[i].l+f[i].r)/2;
 60     if(f[i].l==f[i].r&&f[i].l==goal){
 61         f[i].mx=f[i].sum=v;
 62         return;
 63     }
 64     if(mid>=goal)change(i*2,goal,v);  
 65     else change(i*2+1,goal,v);
 66     pushup(i);
 67 }
 68  
 69 int query(int i,int left,int right) {
 70         int mid=(f[i].l+f[i].r)/2;
 71         if(f[i].l==left&&f[i].r==right) return f[i].sum;
 72         if(mid>=right) return query(i*2,left,right);
 73         if(mid<left) return query(i*2+1,left,right);
 74         return (query(i*2,left,mid)+query(i*2+1,mid+1,right));
 75 }
 76  
 77 int qmax(int i,int left,int right){
 78     int mid=(f[i].l+f[i].r)/2;
 79     if(f[i].l==left&&f[i].r==right) return f[i].mx;
 80     if(mid>=right) return qmax(i*2,left,right);
 81     if(mid<left) return qmax(i*2+1,left,right);
 82     return max(qmax(i*2,left,mid),qmax(i*2+1,mid+1,right));
 83 }
 84 void insert(int u,int v){
 85     e[++tot].go=v;e[tot].next=head[u];head[u]=tot;
 86 }
 87 void ins(int u,int v){
 88     insert(u,v);insert(v,u);
 89 }
 90 void dfs(int x){
 91     s[x]=1;
 92     for(int y=son[x]=0,i=head[x];i;i=e[i].next){
 93         if(dep[y=e[i].go]==0){
 94             dep[y]=dep[x]+1;fa[y]=x;dfs(y);
 95             s[x]+=s[y];if(s[y]>s[son[x]])son[x]=y;
 96         }
 97     }
 98 }
 99 void dfs2(int x,int chain){
100     p[x]=++cnt;top[x]=chain;a[p[x]]=w[x];
101     if(son[x])dfs2(son[x],chain);
102     for(int i=head[x],y=e[i].go;i;i=e[i].next,y=e[i].go)
103         if(y!=fa[x]&&y!=son[x])dfs2(y,y);
104 }
105 int solvesum(int x,int y){
106     int ans=0;
107     while(top[x]!=top[y]){
108         if(dep[top[x]]<dep[top[y]])swap(x,y);
109         ans+=query(1,p[top[x]],p[x]);
110         x=fa[top[x]];
111     }
112     if(dep[x]>dep[y])swap(x,y);
113     ans+=query(1,p[x],p[y]);
114     return ans;
115 }
116 int solvemax(int x,int y){
117     int ans=-inf;
118     while(top[x]!=top[y]){
119         if(dep[top[x]]<dep[top[y]])swap(x,y);
120         ans=max(ans,qmax(1,p[top[x]],p[x]));
121         x=fa[top[x]];
122     }
123     if(dep[x]>dep[y])swap(x,y);
124     ans=max(ans,qmax(1,p[x],p[y]));
125     return ans;
126 }
127 
128 int main(){
129     //freopen("input.txt","r",stdin);
130     //freopen("output.txt","w",stdout);
131     int n=read();dep[1]=1;
132     for1(i,n-1){
133         int u=read(),v=read();
134         ins(u,v);
135     }
136     for1(i,n)w[i]=read();
137     dfs(1);dfs2(1,1);
138     build(1,1,n);
139     n=read();
140     for1(i,n){
141         char ch=getchar();
142         while(ch!='Q'&&ch!='C')ch=getchar();
143         if(ch=='Q'){
144             ch=getchar();
145             if(ch=='M'){
146                 int x=read(),y=read();
147                 printf("%d\n",solvemax(x,y));
148             }
149             else{
150                 int x=read(),y=read();
151                 printf("%d\n",solvesum(x,y));
152             }
153         }
154         else{
155             int x=read(),y=read();
156             change(1,p[x],y);
157         }
158     }
159     return 0;
160 }
View Code

 

posted @ 2016-01-14 08:20  HTWX  阅读(268)  评论(0编辑  收藏  举报