【BZOJ1036】 树的统计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
 
 
【题意】

  给出一棵树,每个点有一个权值,要求三种操作:1.修改某个点的权值,2.询问x到y路径上各点的权值最大值,3.询问x到y路径上各点的权值之和。

 

【分析】

  树链剖分+线段树维护。这题维护的是点的值。

 

代码如下:

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<algorithm>
  6 using namespace std;
  7 #define Maxn 30010
  8 #define INF 0xfffffff
  9 
 10 struct node
 11 {
 12     int x,y,next;
 13 }t[2*Maxn];int len=0;
 14 
 15 int first[Maxn],fa[Maxn],dep[Maxn],top[Maxn],w[Maxn],size[Maxn],son[Maxn];
 16 int wl=0;
 17 
 18 struct nnode
 19 {
 20     int l,r,lc,rc,mx,sum;
 21 }tr[2*Maxn];int tl=0;
 22 
 23 int mymax(int x,int y) {return x>y?x:y;}
 24 
 25 void ins(int x,int y)
 26 {
 27     t[++len].x=x;t[len].y=y;
 28     t[len].next=first[x];first[x]=len;
 29 }
 30 
 31 void dfs1(int x,int f)
 32 {
 33     dep[x]=dep[f]+1;
 34     size[x]=1;fa[x]=f;son[x]=0;
 35     for(int i=first[x];i;i=t[i].next) if(t[i].y!=f)
 36     {
 37         dfs1(t[i].y,x);
 38         size[x]+=size[t[i].y];
 39         if(size[t[i].y]>size[son[x]]) son[x]=t[i].y;
 40     }
 41 }
 42 
 43 void dfs2(int x,int tp)
 44 {
 45     top[x]=tp;w[x]=++wl;
 46     if(size[x]!=1) dfs2(son[x],tp);
 47     for(int i=first[x];i;i=t[i].next) if(t[i].y!=fa[x]&&t[i].y!=son[x])
 48     {
 49         dfs2(t[i].y,t[i].y);
 50     }
 51 }
 52 
 53 int build(int l,int r)
 54 {
 55     int x=++tl;
 56     tr[x].l=l;tr[x].r=r;tr[x].mx=-INF;tr[x].sum=0;
 57     if(l!=r)
 58     {
 59         int mid=(l+r)>>1;
 60         tr[x].lc=build(l,mid);
 61         tr[x].rc=build(mid+1,r);
 62     }
 63     return x;
 64 }
 65 
 66 void change(int x,int y,int z)
 67 {
 68     if(tr[x].l==tr[x].r)
 69     {
 70         tr[x].mx=tr[x].sum=z;
 71         return;
 72     }
 73     int mid=(tr[x].l+tr[x].r)>>1;
 74     if(y<=mid) change(tr[x].lc,y,z);
 75     else change(tr[x].rc,y,z);
 76     tr[x].mx=mymax(tr[tr[x].lc].mx,tr[tr[x].rc].mx);
 77     tr[x].sum=tr[tr[x].lc].sum+tr[tr[x].rc].sum;
 78 }
 79 
 80 int queryt(int x,int l,int r,bool p)
 81 {
 82     if(tr[x].l==l&&tr[x].r==r)
 83     {
 84         if(p) return tr[x].mx;
 85         return tr[x].sum;
 86     }
 87     int mid=(tr[x].l+tr[x].r)>>1;
 88     if(r<=mid) return queryt(tr[x].lc,l,r,p);
 89     else if(l>mid) return queryt(tr[x].rc,l,r,p);
 90     if(p) return mymax(queryt(tr[x].lc,l,mid,p),queryt(tr[x].rc,mid+1,r,p));
 91     return queryt(tr[x].lc,l,mid,p)+queryt(tr[x].rc,mid+1,r,p);
 92 }
 93 
 94 int query(int x,int y,bool p)
 95 {
 96     int f1=top[x],f2=top[y];
 97     int ans=0;
 98     if(p) ans=-INF;
 99     while(f1!=f2)
100     {
101         if(dep[f1]<dep[f2])
102         {
103             swap(f1,f2);
104             swap(x,y);
105         }
106         if(p) ans=mymax(ans,queryt(1,w[f1],w[x],p));
107         else ans+=queryt(1,w[f1],w[x],p);
108         x=fa[f1];
109         f1=top[x];
110     }
111     if(dep[x]<dep[y]) swap(x,y);
112     if(p) ans=mymax(ans,queryt(1,w[y],w[x],p));
113     else ans+=queryt(1,w[y],w[x],p);
114     return ans;
115 }
116 
117 int main()
118 {
119     int n;
120     scanf("%d",&n);
121     memset(first,0,sizeof(first));
122     for(int i=1;i<n;i++)
123     {
124         int x,y;
125         scanf("%d%d",&x,&y);
126         ins(x,y);ins(y,x);
127     }
128     dep[0]=0;size[0]=0;
129     dfs1(1,0);
130     dfs2(1,1);
131     build(1,n);
132     for(int i=1;i<=n;i++)
133     {
134         int x;
135         scanf("%d",&x);
136         change(1,w[i],x);
137     }
138     int m;
139     char s[10];
140     scanf("%d",&m);
141     while(m--)
142     {
143         int x,y;
144         scanf("%s%d%d",s,&x,&y);
145         if(s[0]=='C')
146         {
147             change(1,w[x],y);
148         }
149         else if(s[1]=='S')
150         {
151             printf("%d\n",query(x,y,0));
152         }
153         else
154         {
155             printf("%d\n",query(x,y,1));
156         }
157     }
158     return 0;
159 }
[BZOJ1036]

 

2016-05-10 16:54:19

 

posted @ 2016-05-10 16:52  konjak魔芋  阅读(177)  评论(0编辑  收藏  举报