bzoj 1036 [ZJOI2008]树的统计Count 点权lct
来源:互联网 发布:安卓手游刷元宝软件 编辑:程序博客网 时间:2024/06/04 23:22
题目:
http://www.lydsy.com/JudgeOnline/problem.php?id=1036
题意:
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”的操作,每行输出一个整数表示要求输出的结果。
思路:
本题树形没有发生变化,可以用树链剖分做。用来练LCT
#include <bits/stdc++.h>using namespace std;const int N = 30000 + 10, INF = 0x3f3f3f3f;struct edge{ int to, next;}g[N*2];int son[N][2], key[N], fat[N], maxval[N], sum[N];bool rev[N];int top, stk[N];int cnt, head[N];void init(){ cnt = 0; memset(head, -1, sizeof head); memset(son, 0, sizeof son); memset(key, 0, sizeof key); memset(fat, 0, sizeof fat); memset(maxval, 0, sizeof maxval); memset(sum, 0, sizeof sum); memset(rev, 0, sizeof rev); maxval[0] = -INF;//这里设为无穷小,因为这个wa一次,真是智障}void add_edge(int v, int u){ g[cnt].to = u, g[cnt].next = head[v], head[v] = cnt++;}void dfs(int v, int fa){ fat[v] = fa; for(int i = head[v]; ~i; i = g[i].next) { int u = g[i].to; if(u == fa) continue; dfs(u, v); }}bool is_root(int x){ return son[fat[x]][0] != x && son[fat[x]][1] != x;}void push_up(int x){ maxval[x] = max(key[x], max(maxval[son[x][0]], maxval[son[x][1]])); sum[x] = key[x] + sum[son[x][0]] + sum[son[x][1]];}void push_down(int x){ if(rev[x]) { swap(son[x][0], son[x][1]); rev[son[x][0]] ^= 1, rev[son[x][1]] ^= 1; rev[x] ^= 1; }}void Rotate(int x){ int y = fat[x], p = son[y][0] == x; son[y][!p] = son[x][p], fat[son[x][p]] = y; if(! is_root(y)) son[fat[y]][son[fat[y]][1]==y] = x; fat[x] = fat[y]; son[x][p] = y, fat[y] = x; push_up(y);}void splay(int x){ top = 0; stk[++top] = x; for(int i = x; !is_root(i); i = fat[i]) stk[++top] = fat[i]; for(int i = top; i >= 1; i--) push_down(stk[i]); while(! is_root(x)) { int y = fat[x], z = fat[y]; if(is_root(y)) Rotate(x); else { if((x == son[y][0]) ^ (y == son[z][0])) Rotate(x), Rotate(x); else Rotate(y), Rotate(x); } } push_up(x);}void access(int x){ int y = 0; while(x) { splay(x); son[x][1] = y; push_up(x); y = x, x = fat[x]; }}void make_root(int x){ access(x); splay(x); rev[x] ^= 1;}void update(int x, int v){ key[x] = v; push_up(x); splay(x);}int query(int x, int y, int f){ make_root(x); access(y); splay(y); return f == 1 ? maxval[y] : sum[y];}int main(){ int n, m, x, y; scanf("%d", &n); init(); for(int i = 1; i <= n-1; i++) { scanf("%d%d", &x, &y); add_edge(x, y); add_edge(y, x); } for(int i = 1; i <= n; i++) { scanf("%d", &key[i]); maxval[i] = sum[i] = key[i]; } dfs(1, 0); scanf("%d", &m); char opt[20]; for(int i = 1; i <= m; i++) { scanf("%s%d%d", opt, &x, &y); if(opt[0] == 'C') update(x, y); else if(opt[1] == 'M') printf("%d\n", query(x, y, 1)); else printf("%d\n", query(x, y, 2)); } return 0;}
阅读全文
0 0
- bzoj 1036 [ZJOI2008]树的统计Count 点权lct
- BZOJ 1036: [ZJOI2008]树的统计Count (LCT题解)
- HYSBZ/BZOJ 1036 [ZJOI2008] 树的统计Count - 动态树LCT
- [BZOJ1036][ZJOI2008]树的统计Count && LCT
- BZOJ 1036: [ZJOI2008]树的统计Count
- BZOJ 1036: [ZJOI2008]树的统计Count
- 【BZOJ 1036】[ZJOI2008]树的统计Count
- bzoj 1036: [ZJOI2008]树的统计Count
- BZOJ 1036 [ZJOI2008]树的统计Count
- BZOJ 1036: [ZJOI2008]树的统计Count
- BZOJ 1036 [ZJOI2008]树的统计Count
- bzoj 1036 [ZJOI2008]树的统计Count
- 【bzoj】1036: [ZJOI2008]树的统计Count
- [BZOJ]1036: [ZJOI2008]树的统计Count
- BZOJ 1036 [ZJOI2008] 树的统计Count
- BZOJ 1036: [ZJOI2008]树的统计Count
- BZOJ 1036 [ZJOI2008]树的统计Count
- 【bzoj 1036】 [ZJOI2008]树的统计Count
- caffe安装心得cpu(only)
- Unity3d--矩形Rect
- hdu 6202 cube cube cube
- bzoj 1638: [Usaco2007 Mar]Cow Traffic 奶牛交通(拓扑排序?+DP)
- 结合Scikit-learn介绍几种常用的特征选择方法
- bzoj 1036 [ZJOI2008]树的统计Count 点权lct
- 多线程编程学习二(对象及变量的并发访问)
- synchronized 与 Lock,wait() 与notify()/notifyAll() 的那点事
- android中?attr/**与@drawable/**或@color/**等的区别及用法
- 二维有序数组查找
- JavaScript的组成--BOM浏览器对象模型
- 文件的读写2
- 判断指定日子最接近的日期
- PLSQL Developer 64位下载