http://acm.hdu.edu.cn/showproblem.php?pid=3966

题意:有n个点n-1条边,每个点有一个权值,有两种操作:询问一个点上权值是多少和修改u到v这条链上的权值。

思路:树链剖分。学习地址:http://blog.sina.com.cn/s/blog_7a1746820100wp67.html   http://blog.csdn.net/acdreamers/article/details/10591443

 #include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <string>
#include <iostream>
#include <stack>
#include <map>
#include <queue>
using namespace std;
#define N 50010
#define INF 0x3f3f3f3f
#define lson rt<<1, l, m
#define rson rt<<1|1, m+1, r
struct node
{
int u, v, next;
}edge[N*];
int tot, head[N]; //存边部分
int tim, son[N], tid[N], fa[N], depth[N], size[N], top[N], num[N], rak[N]; //树剖部分
//分别对应DFS的时间、重儿子、节点的时间戳、父节点、节点深度、该节点的子树的节点数、树链中的头节点、初始节点权值、rak[i]表示时间戳为i的节点是rak[i](在线段树中的位置)
int tree[N<<], col[N<<]; //线段树部分
int n; void init()
{
tim = tot = ;
memset(head, -, sizeof(head));
memset(son, -, sizeof(son));
} void add(int u, int v)
{
edge[tot].next = head[u]; edge[tot].u = u; edge[tot].v = v; head[u] = tot++;
} void dfs1(int u, int f, int d)
{
size[u] = ;
depth[u] = d;
fa[u] = f;
for(int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].v;
if(f == v) continue;
dfs1(v, u, d + );
if(size[v] > size[son[u]] || son[u] == -) son[u] = v;
size[u] += size[v];
}
} void dfs2(int u, int f)
{
top[u] = f;
tid[u] = ++tim;
rak[tid[u]] = u;
if(son[u] == -) return ;
dfs2(son[u], f); //是重儿子的话
for(int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].v;
if(v != son[u] && v != fa[u]) dfs2(v, v); //不是重儿子的话
}
} void PushDown(int rt, int len)
{
if(col[rt]) {
col[rt<<] += col[rt];
col[rt<<|] += col[rt];
tree[rt<<] += (len - (len >> )) * col[rt];
tree[rt<<|] += (len >> ) * col[rt];
col[rt] = ;
}
} void Build(int rt, int l, int r)
{
col[rt] = ;
tree[rt] = ;
if(l == r) {
tree[rt] = num[rak[l]];
return ;
}
int m = (l + r) >> ;
Build(lson);
Build(rson);
} void Update(int rt, int l, int r, int L, int R, int val)
{
if(L <= l && r <= R) {
col[rt] += val;
tree[rt] += val * (r - l + );
return ;
}
PushDown(rt, r - l + );
int m = (l + r) >> ;
if(L <= m) Update(lson, L, R, val);
if(R > m) Update(rson, L, R, val);
} int Query(int rt, int l, int r, int id)
{
if(l == r && l == id) return tree[rt];
PushDown(rt, r - l + );
int m = (l + r) >> ;
if(id <= m) return Query(lson, id);
else return Query(rson, id);
} void Change(int u, int v, int val)
{
while(top[u] != top[v]) {
if(depth[top[u]] < depth[top[v]]) swap(u, v);
Update(, , n, tid[top[u]], tid[u], val); //父节点编号小
u = fa[top[u]]; //!!!
}
if(depth[u] > depth[v]) swap(u, v);
Update(, , n, tid[u], tid[v], val);
} int main()
{
int m, q, id, u, v, val;
char s[];
while(~scanf("%d%d%d", &n, &m, &q)) {
init();
for(int i = ; i <= n; i++) scanf("%d", &num[i]);
for(int i = ; i < m; i++) {
scanf("%d%d", &u, &v);
add(u, v); add(v, u);
}
dfs1(, -, );
dfs2(, );
Build(, , n);
while(q--) {
scanf("%s", s);
if(s[] == 'Q') {
scanf("%d", &id);
printf("%d\n", Query(, , n, tid[id]));
} else {
scanf("%d%d%d", &u, &v, &val);
if(s[] == 'D') val = -val;
Change(u, v, val);
}
}
}
return ;
}

HDU 3966:Aragorn's Story(树链剖分)的更多相关文章

  1. HDU 3966 Aragorn's Story 树链剖分+树状数组 或 树链剖分+线段树

    HDU 3966 Aragorn's Story 先把树剖成链,然后用树状数组维护: 讲真,研究了好久,还是没明白 树状数组这样实现"区间更新+单点查询"的原理... 神奇... ...

  2. Hdu 3966 Aragorn's Story (树链剖分 + 线段树区间更新)

    题目链接: Hdu 3966 Aragorn's Story 题目描述: 给出一个树,每个节点都有一个权值,有三种操作: 1:( I, i, j, x ) 从i到j的路径上经过的节点全部都加上x: 2 ...

  3. HDU 3966 Aragorn's Story(树链剖分)(线段树区间修改)

    Aragorn's Story Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  4. HDU 3966 Aragorn's Story 树链剖分+BIT区间修改/单点询问

    Aragorn's Story Description Our protagonist is the handsome human prince Aragorn comes from The Lord ...

  5. HDU 3966 Aragorn's Story 树链剖分

    Link: http://acm.hdu.edu.cn/showproblem.php?pid=3966 这题注意要手动扩栈. 这题我交g++无限RE,即使手动扩栈了,但交C++就过了. #pragm ...

  6. hdu 3966 Aragorn's Story : 树链剖分 O(nlogn)建树 O((logn)²)修改与查询

    /** problem: http://acm.hdu.edu.cn/showproblem.php?pid=3966 裸板 **/ #include<stdio.h> #include& ...

  7. hdu 3966 Aragorn's Story 树链剖分 按点

    Aragorn's Story Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  8. HDU 3966 Aragorn's Story (树链剖分入门题)

    树上路径区间更新,单点查询. 线段树和树状数组都可以用于本题的维护. 线段树: #include<cstdio> #include<iostream> #include< ...

  9. HDU 3966 Aragorn's Story (树链点权剖分,成段修改单点查询)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3966 树链剖分的模版,成段更新单点查询.熟悉线段树的成段更新的话就小case啦. //树链剖分 边权修 ...

  10. HDU 3966 Aragorn's Story 树链拋分

    一.写在前面 终于开始开坑link-cut-tree这个了,对于网上找到的大佬的前进路线,进行了一番研发,发现实际上可以实现对于树链拋分的制作.经历了若干长时间之后终于打了出来(为什么每次学什么东西都 ...

随机推荐

  1. Java遇见HTML——JSP篇之JSP状态管理

    一.http协议的无状态 无状态性是指,当浏览器发送请求给服务器的时候,服务器响应客户端请求.但是当同一个浏览器再次发送请求给服务器的时候,服务器并不知道他就是刚才的那个浏览器.简单的说,就是服务器不 ...

  2. Java 找到数组中两个元素相加等于指定数的所有组合

    思路1:可以用hash表来存储数组中的元素,这样我们取得一个数后,去判断sum - val 在不在数组中,如果在数组中,则找到了一对二元组,它们的和为sum,该算法的缺点就是需要用到一个hash表,增 ...

  3. 防止IE不支持console.log报错

    function log(msg){ if (window["console"]){//判断是否是IE console.log(msg); } }

  4. Formatting Domain Names--域名可以由哪些字符串组成

    the domain name can include any of the following printable ASCII characters (excluding spaces): a-z ...

  5. Gunicorn + Django 部署

    1. 下载gunicorn pip install gunicorn 2. 运行 gunicorn AutoSa.wsgi:application ## AutoSa为我project的名字,后面的不 ...

  6. Rman备份的保留策略(retention policy)

    什么是备份的保留策略(retention policy) 保留策略就是指某份备份是否要保留以及保留多久.可以使用configure retention policy命令来创建一个一致的.自动的备份保留 ...

  7. 通用窗口类 Inventory Pro 2.1.2 Demo1(下续篇 ),物品消耗扇形显示功能

    本篇想总结的是Inventory Pro中通用窗口的具体实现,但还是要强调下该插件的重点还是装备系统而不是通用窗口系统,所以这里提到的通用窗口类其实是通用装备窗口类(其实该插件中也有非装备窗口比如No ...

  8. PostgreSQL单机、同步复制、异步复制性能测试对比

    测试环境: •测试机:PC •内存:8GB •CPU:Intel(R) Core(TM) i5-3450 3.10GHz •硬盘:HDD •数据量:20GB •测试工具:pgbench •Postgr ...

  9. Object-C 入门

    该文章转载自:http://sheng.iteye.com/blog/775588一:Objective-C入门 .Cocoa的组成 苹果公司将Cocoa.Carbon.QuickTime和OpenG ...

  10. Java基础(37):Java中日期的显示与格式定值----Date与SimpleDateFormat的试用

    使用 Date 和 SimpleDateFormat 类表示时间 在程序开发中,经常需要处理日期和时间的相关数据,此时我们可以使用 java.util 包中的 Date 类.这个类最主要的作用就是获取 ...