[ZJOI2008]树的统计Count

                                      [ZJOI2008]树的统计Count

【题目描述】

一棵树上有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本身

【输入格式】

输入的第一行为一个整数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之间。

【输出格式】

对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。

【样例输入】

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
  

【样例输出】

4
  1
  2
  2
  10
  6
  5
  6
  5
  16


树剖模板,注意细节

  1 #include <cstring>
  2 #include <ctype.h>
  3 #include <cstdio>
  4 
  5 const int MAXN=60010;
  6 const int INF=1e9;
  7 
  8 int n,q,inr;
  9 
 10 int a[MAXN],id[MAXN],son[MAXN],fa[MAXN];
 11 int rank[MAXN],siz[MAXN],dep[MAXN],top[MAXN];
 12 
 13 struct SegmentTree {
 14     int l,r;
 15     int mx,sum;
 16 };
 17 SegmentTree t[MAXN<<2];
 18 
 19 struct SKT {
 20     int to;
 21     int next;
 22 };
 23 SKT e[MAXN<<2];
 24 
 25 int head[MAXN],tot;
 26 
 27 inline void read(int&x) {
 28     int f=1;register char c=getchar();
 29     for(x=0;!isdigit(c);c=='-'&&(f=-1),c=getchar());
 30     for(;isdigit(c);x=x*10+c-48,c=getchar());
 31     x=x*f;
 32 }
 33 
 34 inline void add(int x,int y) {
 35     e[++tot].to=y;
 36     e[tot].next=head[x];
 37     head[x]=tot;
 38 }
 39 
 40 void Dfs_1(int now,int f) {
 41     dep[now]=dep[f]+1;
 42     siz[now]=1;
 43     fa[now]=f;
 44     for(int i=head[now];i;i=e[i].next) {
 45         int to=e[i].to;
 46         if(to==f) continue;
 47         Dfs_1(to,now);
 48         siz[now]+=siz[to];
 49         if(son[now]==-1||siz[son[now]]<siz[to]) son[now]=to;
 50     }
 51 }
 52 
 53 void Dfs_2(int now,int tp) {
 54     top[now]=tp;
 55     id[now]=++inr;
 56     rank[id[now]]=now;
 57     if(son[now]==-1) return;
 58     Dfs_2(son[now],tp);
 59     for(int i=head[now];i;i=e[i].next) {
 60         int to=e[i].to;
 61         if(to==fa[now]||to==son[now]) continue;
 62         Dfs_2(to,to);
 63     }
 64 }
 65 
 66 inline int max(int a,int b) {
 67     return a<b?b:a;
 68 }
 69 
 70 inline void swap(int&x,int&y) {
 71     int t=x;x=y;y=t;
 72 }
 73 
 74 inline void up(int now) {
 75     t[now].sum=t[now<<1].sum+t[now<<1|1].sum;
 76     t[now].mx=max(t[now<<1].mx,t[now<<1|1].mx);
 77     return;
 78 }
 79 
 80 void build_tree(int now,int l,int r) {
 81     t[now].l=l;t[now].r=r;
 82     if(l==r) {
 83         t[now].mx=t[now].sum=a[rank[l]];
 84         return;
 85     }
 86     int mid=(l+r)>>1;
 87     build_tree(now<<1,l,mid);
 88     build_tree(now<<1|1,mid+1,r);
 89     up(now);
 90 }
 91 
 92 void modify(int now,int pos,int val) {
 93     if(t[now].l==t[now].r) {
 94         t[now].sum=val;
 95         t[now].mx=val;
 96         return;
 97     }
 98     t[now].mx=-INF;
 99     int mid=(t[now].l+t[now].r)>>1;
100     if(pos<=mid) modify(now<<1,pos,val);
101     else modify(now<<1|1,pos,val);
102     up(now);
103 }
104 
105 int query_max(int now,int l,int r) {
106     int ans=-INF;
107     if(l<=t[now].l&&r>=t[now].r) return t[now].mx;
108     int mid=(t[now].l+t[now].r)>>1;
109     if(l<=mid) ans=max(ans,query_max(now<<1,l,r));
110     if(r>mid) ans=max(ans,query_max(now<<1|1,l,r));
111     return ans;
112 }
113 
114 int query_sum(int now,int l,int r) {
115     int ans=0;
116     if(l<=t[now].l&&r>=t[now].r) return t[now].sum;
117     int mid=(t[now].l+t[now].r)>>1;
118     if(l<=mid) ans+=query_sum(now<<1,l,r);
119     if(r>mid) ans+=query_sum(now<<1|1,l,r);
120     return ans;
121 }
122 
123 inline void Pre_query(int x,int y,char c) {
124     int ans_mx=-INF,ans_sum=0;
125     while(top[x]!=top[y]) {
126         if(dep[top[x]]<dep[top[y]]) swap(x,y);
127         if(c=='X') ans_mx=max(ans_mx,query_max(1,id[top[x]],id[x]));
128         else ans_sum+=query_sum(1,id[top[x]],id[x]);
129         x=fa[top[x]];
130     }
131     if(dep[x]>dep[y]) swap(x,y);
132     if(c=='X') ans_mx=max(ans_mx,query_max(1,id[x],id[y])),printf("%d
",ans_mx);
133     else ans_sum+=query_sum(1,id[x],id[y]),printf("%d
",ans_sum);
134     return;
135 }
136 
137 int hh() {
138     freopen("bzoj_1036.in","r",stdin);
139     freopen("bzoj_1036.out","w",stdout);
140     read(n);
141     int x,y,z;
142     char opt[10];
143     for(int i=1;i<n;++i) {
144         read(x);read(y);
145         add(x,y);add(y,x);
146     }
147     memset(son,-1,sizeof son);
148     for(int i=1;i<=n;++i) read(a[i]);
149     Dfs_1(1,0);Dfs_2(1,1);
150     build_tree(1,1,inr);
151     read(q);
152     while(q--) {
153         scanf("%s",opt);read(x);read(y);
154         if(opt[0]!='Q') modify(1,id[x],y);
155         else Pre_query(x,y,opt[3]);
156     }
157     return 0;
158 }
159 
160 int sb=hh();
161 int main() {;}
代码



作者:乌鸦坐飞机
出处:http://www.cnblogs.com/whistle13326/
新的风暴已经出现 怎么能够停止不前 穿越时空 竭尽全力 我会来到你身边 微笑面对危险 梦想成真不会遥远 鼓起勇气 坚定向前 奇迹一定会出现

 
原文地址:https://www.cnblogs.com/whistle13326/p/7416258.html