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 ...
随机推荐
- mysql limit分页优化方法分享
同样是取10条数据 select * from yanxue8_visit limit 10000,10 和 select * from yanxue8_visit limit 0,10 就不是 ...
- Hadoop提供的reduce函数中Iterable 接口只能遍历一次的问题
今天在写MapReduce中的reduce函数时,碰到个问题,特此记录一下: void reduce(key, Iterable<*>values,...) { for(* v:value ...
- sbt is a build tool for Scala, Java, and more
http://www.scala-sbt.org/0.13/docs/index.html sbt is a build tool for Scala, Java, and more. It requ ...
- 20170225-第一件事:SAP模块清单
第一件事:SAP模块清单 AM 资产会计 资产会计BC SAP Netweaver SAP NetweaverBW 业务信息仓库 业务信息仓库CA 常规跨应用程序 常规跨越应用程序CO 控制 控制 C ...
- CWnd中PreCreateWindow、PreSubclassWindow、SubclassWindow
原文链接:http://blog.chinaunix.net/uid-14607221-id-2794642.html 1. PreCreateWindow: Called by the framew ...
- JOptionPane常用提示框
//JOptionPane.showMessageDialog(parentComponent, message, title, messageType, icon); JOptionPane.sho ...
- javascript查找子节点时,html里的换行可能会被当成节点
1.直接去HTML里找到该换行的地方去掉换行 2.写一个方法把元素类型为空格而且是文本都删除 function del_ff(elem){ var elem_child = elem.childNod ...
- Spring Boot 访问静态资源
方法1一: 在resources目录下建立static的目录,将静态资源放到此处,可以直接访问 访问:127.0.0.1:9010/img/123.png
- TCO 2016 Round 1B
problem 250 Problem Statement Vasa likes to construct sequences of numbers. If you tell him a positi ...
- 【bzoj3282】Tree
LCT模板题: 话说xor和的意思是所有数xor一下: #include<iostream> #include<cstdio> #include<cstring> ...