[HDU 3966] Aragorn's Story 树链剖分
2015-08-27 18:23
549 查看
http://acm.hdu.edu.cn/showproblem.php?pid=3966
题意:给一棵树,并给定各个点权的值,然后有3种操作:
I C1 C2 K : 把 C1 与 C2 的路径上的所有点权值加上 K
D C1 C2 K:把 C1 与 C2 的路径上的所有点权值减去 K
Q C:查询节点编号为C的权值
思路:树链剖分,先进行剖分,然后用线段树或 splay 去维护即可
注意:代码前面加上#pragma comment(linker, “/STACK:1024000000,1024000000”)调整栈的大小
题意:给一棵树,并给定各个点权的值,然后有3种操作:
I C1 C2 K : 把 C1 与 C2 的路径上的所有点权值加上 K
D C1 C2 K:把 C1 与 C2 的路径上的所有点权值减去 K
Q C:查询节点编号为C的权值
思路:树链剖分,先进行剖分,然后用线段树或 splay 去维护即可
注意:代码前面加上#pragma comment(linker, “/STACK:1024000000,1024000000”)调整栈的大小
[code]#pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <cstring> #include <iostream> using namespace std;/ const int maxn = 50010; const int inf = (1<<31)-1; struct node{ //线段树结构体 int l, r; int key,lazy; }; struct side{ //树的结构体 int to; int next; }; int n,m,p,top; int mapn[maxn]; int head[maxn]; side ed[maxn<<1]; node tr[maxn<<2]; int son[maxn], fa[maxn], siz[maxn]; //重儿子,父结点,以自己为根的子树的结点个数 int pre[maxn], deep[maxn], has[maxn], ran[maxn]; //树链的顶部,结点深度,在线段树中的位置,在线段对应树种编号 int add(int x, int y) //建边 { ed[top].to = y; ed[top].next = head[x]; head[x] = top++; return 0; } int Dfs_1(int rt, int d) //求出siz, deep, fa,son; { siz[rt] = 1; deep[rt] = d; for(int i = head[rt]; ~i ; i = ed[i].next){ if(ed[i].to != fa[rt]){ fa[ed[i].to] = rt; Dfs_1(ed[i].to, d+1); siz[rt] += siz[ed[i].to]; if(son[rt] == -1 || siz[ed[i].to] > siz[son[rt]]) son[rt] = ed[i].to; } } return 0; } int Dfs_2(int rt, int pr)//求出pre,has, ran; { pre[rt] = pr; has[rt] = top++; ran[has[rt]] = rt; if(son[rt] == -1) return 0; Dfs_2(son[rt], pr); //先遍历重链 for(int i = head[rt]; ~i ; i = ed[i].next){ if(ed[i].to != son[rt] && ed[i].to != fa[rt]){ Dfs_2(ed[i].to, ed[i].to); } } return 0; } int Build(int rt, int l, int r) //构建线段树 { tr[rt].l = l; tr[rt].r = r; tr[rt].lazy = 0; if(l == r){ tr[rt].key = mapn[ran[l]]; return tr[rt].key; } int mid = (l+r)>>1; int sl = Build(rt<<1, l, mid); int sr = Build(rt<<1|1, mid+1, r); tr[rt].key = sl>sr?sl:sr; return tr[rt].key; } inline int push_down(int rt) { if(tr[rt].lazy == 0) return 0; tr[rt<<1].key += tr[rt].lazy; tr[rt<<1].lazy += tr[rt].lazy; tr[rt<<1|1].key += tr[rt].lazy; tr[rt<<1|1].lazy += tr[rt].lazy; tr[rt].lazy = 0; return 0; } int Updata(int rt, int l, int r, int key) //更新线段树 { if(tr[rt].r < l||tr[rt].l > r) return 0; if(l <= tr[rt].l && tr[rt].r <= r){ tr[rt].key += key; tr[rt].lazy += key; return 0; } push_down(rt); Updata(rt<<1, l, r, key); Updata(rt<<1|1, l, r, key); return 0; } int Query(int rt,int l,int r) //线段树上查询 { if(tr[rt].r < l||tr[rt].l > r) return -inf; if(l <= tr[rt].l && tr[rt].r <= r){ return tr[rt].key; } push_down(rt); int sl = Query(rt<<1, l, r); int sr = Query(rt<<1|1, l, r); return sl>sr?sl:sr; } int fun(int x,int y,int z) //确定更新区间 { while(pre[x] != pre[y]){ //更新到最近公共祖先 if(deep[pre[x]] < deep[pre[y]])//先更新深度深的 swap(x,y); Updata(1,has[pre[x]],has[x],z); x = fa[pre[x]]; } if(deep[x] > deep[y]) swap(x,y); Updata(1, has[x], has[y], z); return 0; } int main() { char str[5]; while(~scanf("%d%d%d",&n,&m,&p)) { for(int i = 1; i <= n; i++){ scanf("%d",&mapn[i]); } top = 1; int x, y, z; memset(son, -1, sizeof(son)); memset(head, -1, sizeof(head)); for(int i = 0; i < m; i++){ scanf("%d%d",&x,&y); add(x,y); add(y,x); } top = 1; fa[1] = deep[1] = 1; Dfs_1(1, 1); Dfs_2(1, 1); Build(1, 1, n); for(int i = 0; i < p; i++){ scanf("%s",str); if(str[0] == 'Q'){ scanf("%d",&x); printf("%d\n",Query(1,has[x],has[x])); } else{ scanf("%d%d%d",&x,&y,&z); if(str[0] == 'D') z = -z; fun(x,y,z); } } } return 0; }
相关文章推荐
- 关于google的历史纪录和书签
- POJ 3228 -- Gold Transportation【二分 && 最大流】
- leetcode: (125) Valid Palindrome
- Chrome实验版可同时检查多种语言拼写错误
- Goods:注册页面实现
- 如何下载google play免费应用的apk文件
- 华为oj: 输入n个整数,输出其中最小的k个
- 使用Category 重写frame
- Go语言并发编程(一)
- django学习笔记
- django 日志配置
- zygote oom_score_adj 被设置成1000
- Google 的开源技术protobuf 简介与例子
- 华为oj: 字符串加解密
- 【索引】Geometric Algorithms in 2D::Exercises: Beginner
- ZOJ 3751 Diagonal
- 【索引】Geometric Algorithms in 2D::Examples
- 【索引】Geometric Computations and Algorithms in 3D
- 【索引】Geometric Algorithms in 2D
- Chapter 10. Generic Algorithms