Hdu 3966 Aragorn's Story (树链剖分 + 线段树区间更新)
题目链接:
题目描述:
给出一个树,每个节点都有一个权值,有三种操作:
1:( I, i, j, x ) 从i到j的路径上经过的节点全部都加上x;
2:( D, i, j, x ) 从i到j的路径上经过的节点全部都减去x;
3:(Q, x) 查询节点x的权值为多少?
解题思路:
可以用树链剖分对节点进行hash,然后用线段树维护(修改,查询),数据范围比较大,要对线段树进行区间更新
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std; const int maxn = ;
#define lson(x) 2*x+1
#define rson(x) 2*x+2 struct e
{
int to, next;
}edge[maxn*];
struct node
{
int l, r, val, x;
int Mid ()
{
return (l+r)/;
}
}tree[maxn*];
int val[maxn], x[maxn], deep[maxn], size[maxn], tot, num;
int son[maxn], top[maxn], id[maxn], head[maxn], fa[maxn]; void init ()
{
num = tot =;
memset (head, -, sizeof(head));
} void Add (int from, int to)
{
edge[tot].to = to;
edge[tot].next = head[from];
head[from] = tot ++;
} //找重边
void dfs1 (int u, int f, int dep)
{
son[u] = ;
fa[u] = f;
deep[u] = dep;
size[u] = ; for (int i=head[u]; i!=-; i=edge[i].next)
{
int v = edge[i].to;
if (v == f) continue;
dfs1 (v, u, dep+);
size[u] += size[v];
if (size[son[u]] < size[v])
son[u] = v;
}
} //重边连接成重链
void dfs2 (int u, int tp)
{
top[u] = tp;
id[u] = ++num;
if (son[u]) dfs2 (son[u], tp); for (int i=head[u]; i!=-; i=edge[i].next)
{
int v = edge[i].to;
if (v == fa[u] || v == son[u]) continue;
dfs2 (v, v);
}
} //区间更新线段树,向下一层更新
void pushup (int x)
{
tree[lson(x)].x += tree[x].x;
tree[rson(x)].x += tree[x].x;
tree[lson(x)].val += tree[x].x;
tree[rson(x)].val += tree[x].x;
tree[x].x = ;
} void build (int root, int l, int r)
{
tree[root].l = l;
tree[root].r = r;
tree[root].x = tree[root].val = ; if (l == r)
{
tree[root].val = val[l];
return ;
} build (lson(root), l, tree[root].Mid());
build (rson(root), tree[root].Mid()+, r);
} void updata (int root, int l, int r, int x)
{
if (tree[root].l == l && r == tree[root].r)
{
tree[root].val += x;
tree[root].x += x;
return ;
} if (tree[root].x)
pushup (root); if (r <= tree[root].Mid())
updata (lson(root), l, r, x);
else if (tree[root].Mid() < l)
updata (rson(root), l, r, x);
else
{
updata (lson(root), l, tree[root].Mid(), x);
updata (rson(root), tree[root].Mid()+, r, x);
}
} int query (int root, int x)
{
if (tree[root].l == tree[root].r && tree[root].l == x)
return tree[root].val; if (tree[root].x)
pushup (root); if (x <= tree[root].Mid())
query (lson(root), x);
else
query (rson(root), x);
} //处理节点u,v
void alter (int u, int v,int x)
{
int tp1 = top [u];
int tp2 = top [v]; while (tp1 != tp2)
{//两个节点不在同一个重链上
if (deep[tp1] < deep[tp2])
{
swap (tp1, tp2);
swap (u, v);
}//deep深的重链上升 updata (, id[tp1], id[u], x);
u = fa[tp1];
tp1 = top[u];
} //在同一条重链上
if (deep[u] > deep[v])
swap (u, v);
updata (, id[u], id[v], x); } int main ()
{
int n, m, q; while (scanf ("%d %d %d", &n, &m, &q) != EOF)
{
init ();
for (int i=; i<=n; i++)
scanf ("%d", &x[i]);
for (int i=; i<m; i++)
{
int x, y;
scanf ("%d %d", &x, &y);
Add (x, y);
Add (y, x);
} dfs1 (, , );
dfs2 (, ); //hash原来节点
for (int i=; i<=n; i++)
val[id[i]] = x[i];
build (, , n); while (q --)
{
char str[];
int l, r, x;
scanf ("%s", str); if (str[] == 'Q')
{
scanf ("%d", &x);
printf ("%d\n", query (, id[x]));
}
else if (str[] == 'I')
{
scanf ("%d %d %d", &l, &r, &x);
alter (l, r, x);
}
else
{
scanf ("%d %d %d", &l, &r, &x);
alter (l, r, -x);
} }
}
return ;
}
Hdu 3966 Aragorn's Story (树链剖分 + 线段树区间更新)的更多相关文章
- Aragorn's Story 树链剖分+线段树 && 树链剖分+树状数组
Aragorn's Story 来源:http://www.fjutacm.com/Problem.jsp?pid=2710来源:http://acm.hdu.edu.cn/showproblem.p ...
- HDU 2460 Network(双连通+树链剖分+线段树)
HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链 ...
- 【BZOJ-2325】道馆之战 树链剖分 + 线段树
2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 1153 Solved: 421[Submit][Statu ...
- 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树
[BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...
- BZOJ2243 (树链剖分+线段树)
Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...
- POJ3237 (树链剖分+线段树)
Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...
- bzoj4034 (树链剖分+线段树)
Problem T2 (bzoj4034 HAOI2015) 题目大意 给定一颗树,1为根节点,要求支持三种操作. 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子 ...
- HDU4897 (树链剖分+线段树)
Problem Little Devil I (HDU4897) 题目大意 给定一棵树,每条边的颜色为黑或白,起始时均为白. 支持3种操作: 操作1:将a->b的路径中的所有边的颜色翻转. 操作 ...
- Aizu 2450 Do use segment tree 树链剖分+线段树
Do use segment tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.bnuoj.com/v3/problem_show ...
- 【POJ3237】Tree(树链剖分+线段树)
Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...
随机推荐
- java 调用ant的自己定义task,默认不是build.xml 的一点问题
java 调用ant的自己定义task, File buildFile = new File(".//ee-build.xml"); // 创建一个ANT项目 ...
- ArrayList遍历的4种方法
public class ArrayListDemo { public static void main(String args[]){ List<String> list = new A ...
- Release Candidate
RC_百度百科 https://baike.baidu.com/item/RC/7311964?fr=aladdin RC=Release Candidate,含义是"发布候选版" ...
- 登录日志的访问日志的 统计 MapReduce
登录日志的访问日志的 统计 MapReduce <!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoop-commo ...
- dedecms获取顶级栏目名称、二级栏目名称实现方法
织梦DEDECMS文章.栏目页获取当前页面顶级栏目名称的方法 在用织梦做一些项目时,时常会碰到需要在当前页面调用顶级栏目名称的时候,织梦默认{dede:field name='typename' /} ...
- 逻辑运算符,if、swtch语句(java基础知识三)
1.逻辑运算符的基本用法 * A:逻辑运算符有哪些 &(逻辑与) |(逻辑或) !(逻辑非) ^(逻辑异或) &&(短路与) ||(短路或) * 注意事项: * a:逻辑运算符 ...
- jLim - 紧凑的 JavaScript 框架
1. [代码][JavaScript]代码 /*! * jLim Core * * jLim is a small JavaScript base code. It can be used t ...
- 一步一步学Silverlight 2系列(25):综合实例之Live Search
概述 Silverlight 2 Beta 1版本发布了,无论从Runtime还是Tools都给我们带来了很多的惊喜,如支持框架语言Visual Basic, Visual C#, IronRuby, ...
- fuse的编译安装(Centos7-minimal)
打算寒假在家跟着THU的一个分布式系统的课程:http://thu-cmu.cs.tsinghua.edu.cn/curriculum/dscourse/schedule.htm 第0个lab就是要在 ...
- Opencv+Zbar二维码识别(标准条形码/二维码识别)
使用Opencv+Zbar组合可以很容易的识别图片中的二维码,特别是标准的二维码,这里标准指的是二维码成像清晰,图片中二维码的空间占比在40%~100%之间,这样标准的图片,Zbar识别起来很容易,不 ...