BZOJ[1036] [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
 
树链剖分模板题
 
 
  1 #include<iostream>
  2 #include<cstring>
  3 #include<cstdio>
  4 #include<cstdlib>
  5 #include<cmath>
  6 #include<algorithm>
  7 using namespace std;
  8 int son[30001],fa[30001],v[30001],deep[30001],num[30001];
  9 int d[30001],t[30001],fd[30001];
 10 int s;
 11 struct data
 12 {
 13     int to,next;
 14 }a[60001];
 15 int head[30001];
 16 int cnt=0;
 17 void add(int u,int v){a[cnt].to=v;a[cnt].next=head[u];head[u]=cnt;cnt++;}
 18 int n;
 19 void dfs(int now,int f,int de)
 20 {
 21     fa[now]=f;
 22     deep[now]=de;
 23     num[now]=1;
 24     for(int i=head[now];i>=0;i=a[i].next)
 25     {
 26         if(a[i].to!=f)
 27         {
 28             dfs(a[i].to,now,de+1);
 29             num[now]+=num[a[i].to];
 30             if(num[a[i].to]>num[son[now]]) son[now]=a[i].to;
 31         }
 32     }
 33 }
 34 void dfs1(int now,int f,int tp)
 35 {
 36     t[now]=tp;
 37     d[now]=++s;
 38     fd[s]=now;
 39     if(son[now]) dfs1(son[now],now,tp);
 40     for(int i=head[now];i>=0;i=a[i].next)
 41     {
 42         int v=a[i].to;
 43         if(v!=son[now]&&v!=f) dfs1(v,now,v);
 44     }    
 45 }
 46 int maxn[90005],sum[90005];
 47 void pushup(int l,int r,int o)
 48 {
 49     int lo=o<<1,ro=lo+1;
 50     maxn[o]=max(maxn[lo],maxn[ro]);
 51     sum[o]=sum[lo]+sum[ro];
 52 }
 53 void build(int l,int r,int o)
 54 {
 55     if(l==r)maxn[o]=sum[o]=v[fd[l]];
 56     else
 57     {
 58         int mid=(l+r)>>1,lo=o<<1,ro=lo+1;
 59         build(l,mid,lo);
 60         build(mid+1,r,ro);
 61         pushup(l,r,o);
 62     }
 63 }
 64 
 65 void updata(int l,int r,int o,int m,int va)
 66 {
 67     if(l==m&&r==m) maxn[o]=sum[o]=va;
 68     else
 69     {
 70         int mid=(l+r)>>1,lo=o<<1,ro=lo+1;
 71         if(m>mid) updata(mid+1,r,ro,m,va);
 72         else updata(l,mid,lo,m,va);
 73         pushup(l,r,o);
 74     }
 75 }
 76 int al,ar,Max=-2147483647,Sum=0;
 77 void query(int l,int r,int o)
 78 {
 79     if(l>=al&&r<=ar)
 80     {
 81         Max=max(Max,maxn[o]);
 82         Sum+=sum[o];
 83     }
 84     else
 85     {
 86         int mid=(l+r)>>1,lo=o<<1,ro=lo+1;
 87         if(ar>mid) query(mid+1,r,ro);
 88         if(al<=mid) query(l,mid,lo);
 89     }
 90 }
 91 char ch[20];
 92 void find(int x,int y)
 93 {
 94     Max=-2147483647,Sum=0;
 95     int f1=t[x],f2=t[y];
 96     while(f1!=f2)
 97     {
 98         if(deep[f1]<deep[f2])
 99         {
100             swap(f1,f2);
101             swap(x,y);
102         }
103         al=d[f1],ar=d[x];
104         query(1,n,1);
105         x=fa[f1];
106         f1=t[x];
107     }
108     if(deep[x]>deep[y]) swap(x,y);
109     al=d[x],ar=d[y];
110     query(1,n,1);
111     if(ch[1]=='M') printf("%d\n",Max);
112     else printf("%d\n",Sum);
113 }
114 int main()
115 {
116     memset(head,-1,sizeof(head));
117     scanf("%d",&n);
118     for(int i=1;i<n;i++)
119     {
120         int u1,v1;
121         scanf("%d%d",&u1,&v1);
122         add(u1,v1);
123         add(v1,u1);
124     }
125     for(int i=1;i<=n;i++) scanf("%d",&v[i]);
126     dfs(1,0,1);
127     dfs1(1,0,1);
128     build(1,n,1);
129     int q;
130     scanf("%d",&q);
131     for(int i=1;i<=q;i++)
132     {
133         
134         scanf("%s",ch);
135         int x,y;
136         if(ch[0]=='C')
137         {
138             scanf("%d%d",&x,&y);
139             updata(1,n,1,d[x],y);
140         }
141         else
142         {
143             scanf("%d%d",&x,&y);
144             find(x,y);
145         }
146     }
147     //system("pause");
148 }
View Code

 

posted @ 2017-07-14 10:22  wls001  阅读(142)  评论(0编辑  收藏  举报