BZOJ 1036: [ZJOI2008]树的统计Count
2017-02-14 21:22
351 查看
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
41 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
41
2
2
10
6
5
6
5
16
分析
第一次打树剖,再加上对位运算掌握的不是很好,导致调试了很久。因为我以为位运算的优先级是最高的!!!于是就少加了一个括号,然后就错了。
这个故事告诉我们,我们还是加上括号吧,至少比较安全。
代码
#include <bits/stdc++.h> #define N 30005 #define INF 0x7fffff using namespace std; int val ; struct EDGE { int to,next; }e[N*4]; int next ; int cnt; void add(int x,int y) { e[++cnt].to = y; e[cnt].next = next[x]; next[x] = cnt; } int pre ,tree ; int fa ,son ; int top ; int num ; int dep ; void dfs1(int x,int d,int f) { dep[x] = d; fa[x] = f; num[x] = 1; for (int i = next[x]; i; i = e[i].next) { int v = e[i].to; if (v == f) continue; dfs1(v,d+1,x); num[x] += num[v]; if (!son[x] || num[v] > num[son[x]]) son[x] = v; } } int tot; void dfs2(int x,int k) { top[x] = k; tree[x] = ++tot; pre[tree[x]] = x; if (!son[x]) return ; dfs2(son[x],k); for (int i = next[x]; i; i = e[i].next) { int v = e[i].to; if (v != son[x] && v != fa[x]) dfs2(v,v); } } struct NOTE { int l,r,sum,max; }t[N*4]; void build(int x,int l,int r) { t[x].l = l; t[x].r = r; if (l == r) { t[x].sum = val[pre[l]]; t[x].max = val[pre[l]]; return ; } int mid = (l + r) >> 1; build(x << 1,l,mid); build((x << 1) + 1,mid + 1,r); t[x].sum = t[x << 1].sum + t[(x << 1) + 1].sum; t[x].max = max(t[x << 1].max,t[(x << 1) + 1].max); } void addNum(int k,int x,int s) { if (t[k].l == t[k].r) { t[k].sum += s * (t[k].r - t[k].l + 1); t[k].max += s; return ; } int mid = (t[k].l + t[k].r) >> 1; if (x <= mid) addNum(k << 1,x,s); else addNum((k << 1) + 1,x,s); t[k].sum = t[k << 1].sum + t[(k << 1) + 1].sum; t[k].max = max(t[k << 1].max,t[(k << 1)+1].max); } int getMax(int k,int x,int y) { if (t[k].l >= x && t[k].r <= y) return t[k].max; int mid = (t[k].l + t[k].r) >> 1,o = -INF; if (x <= mid) o = getMax(k<<1,x,y); if (y>mid) o = max(o,getMax((k << 1) + 1,x,y)); t[k].sum = t[k << 1].sum + t[(k << 1) + 1].sum; t[k].max = max(t[k << 1].max,t[(k << 1) + 1].max); return o; } int findMax(int l,int r) { int top1 = top[l]; int top2 = top[r]; int ans = -INF; while (top1 != top2) { if(dep[top1] < dep[top2]) { swap(top1,top2); swap(l,r); } ans = max(ans,getMax(1,tree[top1],tree[l])); l = fa[top1]; top1 = top[l]; } ans = max(ans,(dep[l] > dep[r])?getMax(1,tree[r],tree[l]):getMax(1,tree[l],tree[r])); return ans; } int getSum(int k,int x,int y) { if (t[k].l >= x && t[k].r <= y) return t[k].sum; int mid = (t[k].l + t[k].r) >> 1,o = 0; if (x <= mid) o += getSum(k << 1,x,y); if (y > mid) o += getSum((k << 1) + 1,x,y); t[k].sum = t[k << 1].sum + t[(k << 1) + 1].sum; t[k].max = max(t[k << 1].max,t[(k << 1) + 1].max); return o; } int findSum(int l,int r) { int top1 = top[l]; int top2 = top[r]; int ans = 0; while (top1 != top2) { if(dep[top1] < dep[top2]) { swap(top1,top2); swap(l,r); } ans += getSum(1,tree[top1],tree[l]); l = fa[top1]; top1 = top[l]; } ans += (dep[l] > dep[r])?getSum(1,tree[r],tree[l]):getSum(1,tree[l],tree[r]); return ans; } int main() { int n,q; scanf("%d",&n); for (int i = 1; i < n; i++) { int x,y; scanf("%d%d",&x,&y); add(x,y); add(y,x); } for (int i = 1; i <= n; i++) scanf("%d",&val[i]); dfs1(1,1,0); dfs2(1,1); build(1,1,n); scanf("%d",&q); char ch[10]; for(int i = 1; i <= q; i++) { int x,y; scanf("%s%d%d",ch,&x,&y); if (ch[0] == 'C') addNum(1,tree[x],y - val[x]),val[x] = y; else if (ch[1] == 'M') printf("%d\n",findMax(x,y)); else printf("%d\n",findSum(x,y)); } }
相关文章推荐
- cassandra vs mongo (1)存储引擎
- C语言 · 完数
- 利用IIS应用请求转发ARR实现IIS和tomcat整合共用80端口
- 索引类型及其区别
- JavaScript作用域链
- 宇宙总统
- 2 itk安装记录
- angular.js和ionic框架搭建一个webApp
- vim与gcc
- dfs带状态改变的做法
- android 点击缩略图查看大图
- html5 兼容旧浏览器一例
- 浙江大学研究生2005年上机题java实现
- Project Euler 006 Sum square difference
- (原)SQL Server 系统提供功能的三个疑惑
- Markdown的使用
- [android] 开源项目研究.md
- 策略模式与状态工厂,简单工厂的恩怨
- 卡特兰数总结(转)
- 硬币划分问题