[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\n",ans_mx);
133 else ans_sum+=query_sum(1,id[x],id[y]),printf("%d\n",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/
新的风暴已经出现
怎么能够停止不前
穿越时空 竭尽全力
我会来到你身边
微笑面对危险
梦想成真不会遥远
鼓起勇气 坚定向前
奇迹一定会出现