【bzoj1036】[ZJOI2008]树的统计Count

题意:

I. CHANGE u t : 把结点u的权值改为t

II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值

III. QSUM u v: 询问从点u到点v的路径上的节点的权值和

 

树链剖分

 

siz[v]表示以v为根的子树的节点数

top[v]表示v所在的重链的顶端节点

fa[v]表示v的父亲

son[v]表示与v在同一重链上的v的儿子节点

pos[v]表示v与其父亲节点的连边在线段树中的位置

 

  1 #include<algorithm>
  2 #include<iostream>
  3 #include<cstdlib>
  4 #include<cstring>
  5 #include<cstdio>
  6 #include<cmath>
  7 using namespace std;
  8  
  9 typedef long long LL;
 10  
 11 #define INF 0x7fffffff
 12 #define N 30010
 13  
 14 struct Node
 15 {
 16     LL maxn,sum;
 17 }tr[N<<2];
 18  
 19 struct edge
 20 {
 21     int to,next;
 22 }e[N<<2];
 23  
 24 int cnt,head[N<<2];
 25  
 26 int id,siz[N],top[N],fa[N],son[N];
 27 int d[N],pos[N],v[N];
 28  
 29 char s[15];
 30  
 31 int n,m;
 32 int a,b;
 33  
 34 LL ans,sum;
 35  
 36 void link(int x,int y)
 37 {
 38     e[++cnt]=(edge){y,head[x]};
 39     head[x]=cnt;
 40 }
 41  
 42 void dfs(int x,int y)
 43 {
 44     siz[x]=1;
 45     fa[x]=y;
 46     d[x]=d[y]+1;
 47     int k=0;
 48     for (int i=head[x];i;i=e[i].next)
 49         if (e[i].to!=fa[x])
 50         {
 51             dfs(e[i].to,x);
 52             siz[x]+=siz[e[i].to];
 53             if (siz[e[i].to]>k)
 54                 k=siz[e[i].to],son[x]=e[i].to;
 55         }
 56 }
 57  
 58 void dfs2(int x,int y)
 59 {
 60     top[x]=y;
 61     pos[x]=++id;
 62     if (!son[x])
 63         return ;
 64     dfs2(son[x],y);
 65     for (int i=head[x];i;i=e[i].next)
 66         if (e[i].to!=fa[x] && e[i].to!=son[x])
 67             dfs2(e[i].to,e[i].to);
 68 }
 69  
 70 void pushup(int now)
 71 {
 72     tr[now].sum=tr[now<<1].sum+tr[now<<1|1].sum;
 73     tr[now].maxn=max(tr[now<<1].maxn,tr[now<<1|1].maxn);
 74 }
 75  
 76 void update(int nowl,int nowr,int now,int x,int y)
 77 {
 78     if (nowl==nowr)
 79     {
 80         tr[now].sum=y;
 81         tr[now].maxn=y;
 82         return ;
 83     }
 84     int mid=(nowl+nowr)>>1;
 85     if (x<=mid)
 86         update(nowl,mid,now<<1,x,y);
 87     else
 88         update(mid+1,nowr,now<<1|1,x,y);
 89     pushup(now);
 90 }
 91  
 92 void query(int nowl,int nowr,int now,int x,int y)
 93 {
 94     if (nowl==x && nowr==y)
 95     {
 96         ans=max(ans,tr[now].maxn);
 97         sum+=tr[now].sum;
 98         return ; 
 99     }
100     int mid=(nowl+nowr)>>1;
101     if (y<=mid)
102         query(nowl,mid,now<<1,x,y);
103     else if (x>mid)
104         query(mid+1,nowr,now<<1|1,x,y);
105     else
106         query(nowl,mid,now<<1,x,mid),query(mid+1,nowr,now<<1|1,mid+1,y);
107 }
108  
109 void find(int x,int y)
110 {
111     int f1=top[x],f2=top[y];
112     ans=-INF;
113     sum=0;
114     while (f1!=f2)
115     {
116         if (d[f1]<d[f2])
117             swap(f1,f2),swap(x,y);
118         query(1,n,1,pos[f1],pos[x]);
119         x=fa[f1];
120         f1=top[x];
121     }
122     if (d[x]>d[y])
123         swap(x,y);
124     query(1,n,1,pos[x],pos[y]);
125 }
126  
127 int main()
128 {
129     scanf("%d",&n);
130     for (int i=1;i<n;i++)
131     {
132         scanf("%d%d",&a,&b);
133         link(a,b);
134         link(b,a);
135     }
136     for (int i=1;i<=n;i++)
137         scanf("%d",&v[i]);
138     d[1]=1;
139     dfs(1,0);
140     dfs2(1,1);
141     for (int i=1;i<=n;i++)
142         update(1,n,1,pos[i],v[i]);
143     scanf("%d",&m);
144     int x,y;
145     while (m--)
146     {
147         scanf("%s%d%d",s,&x,&y);
148         if (s[0]=='C')
149             update(1,n,1,pos[x],y);
150         else
151         {
152             find(x,y);
153             if (s[1]=='M')
154                 printf("%lld\n",ans);
155             else
156                 printf("%lld\n",sum);
157         }
158     }
159     return 0;
160 }
161  

 

posted @ 2016-03-28 15:05  Yangjiyuan  阅读(162)  评论(0编辑  收藏  举报