【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

思路

    又是从浙江挂下来的考数据结构的歪风邪气。

  树链剖分。不过我们不以边为元素,而以点为元素。由于一个点有可能被访问两次,所以在判重方面有一些麻烦。

     大体的思想是每次把点向上提的时候处理提到的节点,但不处理当前的节点。。

     恩。。这份代码应该是写的比较差吧,就当复习树链剖分了。

  1 #include <iostream>
  2 #include <cstring>
  3 #include <string>
  4 #include <cstdio>
  5 #include <cstdlib>
  6 #include <cmath>
  7 #include <algorithm>
  8 #include <queue>
  9 #include <stack>
 10 #include <map>
 11 #include <set>
 12 #include <list>
 13 #include <vector>
 14 #include <ctime>
 15 #include <functional>
 16 #define pritnf printf
 17 #define scafn scanf
 18 #define sacnf scanf
 19 #define For(i,j,k) for(int i=(j);i<=(k);(i)++)
 20 #define Clear(a) memset(a,0,sizeof(a))
 21 using namespace std;
 22 typedef unsigned int Uint;
 23 const int INF=0x3fffffff;
 24 ///==============struct declaration==============
 25 
 26 ///==============var declaration=================
 27 const int MAXN=30050;
 28 int n,q,tot=0,k,v,L,R;
 29 int siz[MAXN],son[MAXN],fa[MAXN],top[MAXN],val[MAXN],No[MAXN],depth[MAXN];
 30 int sum[MAXN*5],maxv[MAXN*5];
 31 vector <int> Edge[MAXN];
 32 ///==============function declaration============
 33 void dfs1(int x);void dfs2(int x);void Init();
 34 void Set_Seg(int o,int l,int r);
 35 void update(int o,int l,int r);
 36 int Query_Max(int o,int l,int r);
 37 int Query_Sum(int o,int l,int r);
 38 ///==============main code=======================
 39 int main()
 40 {
 41 #define FILE__
 42 #ifdef FILE__
 43    freopen("input","r",stdin);
 44    freopen("output","w",stdout);
 45 #endif
 46    scanf("%d",&n);
 47    for(int i=1;i<n;i++){
 48       int s,e;scanf("%d%d",&s,&e);
 49       Edge[s].push_back(e);Edge[e].push_back(s);
 50    }
 51    for(int i=1;i<=n;i++)   scanf("%d",val+i);
 52    depth[1]=1;top[1]=1;dfs1(1);dfs2(1);
 53    for(int i=1;i<=n;i++){
 54       v=val[i],k=No[i];
 55       Set_Seg(1,1,n);
 56    }
 57    scanf("%d",&q);
 58    while (q--){
 59       char cmd[10];scanf("%s",cmd);
 60       if (cmd[1]=='M'){///QMAX
 61          int _max=-INF;int u,v;
 62          scanf("%d%d",&u,&v);if (u==v) _max=val[u];
 63           _max=max(_max,val[u]);
 64           _max=max(_max,val[v]);///if the point locates at a top of a Heavy String
 65          while (u!=v){
 66             if (depth[top[u]]<depth[top[v]])  swap(u,v);///Make u is always deeper
 67             if (top[u]==top[v]){///Locate at the same Heavy String
 68                L=No[u],R=No[v];if (L>R) swap(L,R);L++;R--;
 69                if (L<=R)
 70                _max=max(_max,Query_Max(1,1,n));
 71                break;
 72             }
 73             if (top[u]==u){///Top of a heavy string
 74                u=fa[u];
 75                _max=max(_max,val[u]);
 76             }
 77             else{///middle of a heavy string
 78                L=No[top[u]],R=No[u];if (L>R) swap(L,R);R--;
 79                _max=max(_max,Query_Max(1,1,n));u=top[u];
 80             }
 81          }
 82          printf("%d\n",_max);
 83       }
 84       else if (cmd[1]=='S'){///QSUM
 85          int _sum=0;int u,v;
 86          scanf("%d%d",&u,&v);
 87           _sum+=val[u];
 88          if (u!=v) _sum+=val[v];///if the point locates at a top of a Heavy String
 89          while (u!=v){
 90             if (depth[top[u]]<depth[top[v]])  swap(u,v);///Make u is always deeper
 91             if (top[u]==top[v]){///Locate at the same Heavy String
 92                L=No[v],R=No[u];if (L>R) swap(L,R);L++;R--;
 93                if (L<=R)
 94                _sum+=Query_Sum(1,1,n);
 95                break;
 96             }
 97             if (top[u]==u){///Top of a heavy string
 98                u=fa[u];
 99                if (u!=v)
100                _sum+=val[u];
101             }
102             else{///middle of a heavy string
103                L=No[top[u]],R=No[u];if (L>R) swap(L,R);R--;
104                _sum+=Query_Sum(1,1,n);u=top[u];
105             }
106          }
107          printf("%d\n",_sum);
108       }
109       else if (cmd[1]=='H'){///Change
110          scanf("%d%d",&k,&v);val[k]=v;k=No[k];
111          Set_Seg(1,1,n);
112       }
113    }
114    return 0;
115 }
116 ///================fuction code====================
117 void dfs1(int x){
118    siz[x]=1;son[x]=-1;
119    for(int i=0;i<Edge[x].size();i++){
120       int &e=Edge[x][i];
121       if (fa[x]==e)  continue;
122       fa[e]=x;depth[e]=depth[x]+1;dfs1(e);
123       siz[x]+=siz[e];
124       if (son[x]==-1||siz[son[x]]<siz[e])
125          son[x]=e;
126    }
127 }
128 void dfs2(int x){
129    No[x]=++tot;
130    if (siz[x]!=1) {
131       top[son[x]]=top[x];
132       dfs2(son[x]);
133    }
134    for(int i=0;i<Edge[x].size();i++){
135       int &e=Edge[x][i];
136       if (son[x]==e||fa[x]==e) continue;
137       top[e]=e;dfs2(e);
138    }
139 }
140 void Set_Seg(int o,int l,int r){
141    int m=(l+r)>>1,lc=o*2,rc=o*2+1;
142    if (l==r){
143       sum[o]=maxv[o]=v;
144       return;
145    }
146    if (m>=k)   Set_Seg(lc,l,m);
147    else  Set_Seg(rc,m+1,r);
148    update(o,l,r);
149 }
150 void update(int o,int l,int r){
151    int lc=o*2,rc=o*2+1;
152    sum[o]=sum[lc]+sum[rc];
153    maxv[o]=max(maxv[lc],maxv[rc]);
154 }
155 int Query_Max(int o,int l,int r){
156    if (L<=l&&r<=R)
157       return maxv[o];
158    int m=(l+r)>>1,lc=o*2,rc=o*2+1;
159    int Left=-INF,Right=-INF;
160    if (m>=L)   Left=Query_Max(lc,l,m);
161    if (m<R)    Right=Query_Max(rc,m+1,r);
162    return max(Left,Right);
163 }
164 int Query_Sum(int o,int l,int r){
165    if (L<=l&&r<=R)
166       return sum[o];
167    int m=(l+r)>>1,lc=o*2,rc=o*2+1;
168    int Left=0,Right=0;
169    if (m>=L)   Left=Query_Sum(lc,l,m);
170    if (m<R)    Right=Query_Sum(rc,m+1,r);
171    return Left+Right;
172 }
BZOJ 1036

 

转载于:https://www.cnblogs.com/Houjikan/p/4322274.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值