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 ...
随机推荐
- Appium,IOS 模拟器,Java工程搭建
首先进入sample code Test App 有TestApp.xcodeproj文件的工程目录下 下编译出TestApp.app文件 1.新建 java 工程 2.import需要的包 新建cl ...
- sanic官方文档解析之ssl,debug mode模式和test(测试)
1,ssl 示例: 可选择的SSLContent from sanic import Sanic import ssl context = ssl.create_default_context(pur ...
- java中方法中声明三个点“...”作用
public class Test { public static void main(String[] args) { String str[] = {"s"," ...
- PPAPI与Browser间使用AsyncIPC通信
採用AsyncIpc这个项目(https://github.com/hicdre/AsyncIpc).来完毕PPAPI Plugin进程与Browser进程的通信. foruok原创.如需转载请关注f ...
- yarn笔记
常用命令: 创建项目:yarn init 安装依赖包:yarn == yarn install 添加依赖包:yarn add Yarn命令列表 命令 操作 参数 标签 yarn add 添加依赖包 包 ...
- MapReduce Join的使用
一.Map端Join 可连接两个都非常大的数据集之间可使用map端连接,数据在到达map端之前就执行连接操作. 需满足: 两个要连接的数据集都先划分成相同数量的分区,相同的key要保证在同一分区中(每 ...
- Codeforces-707D:Persistent Bookcase (离线处理特殊的可持久化问题&&Bitset)
Recently in school Alina has learned what are the persistent data structures: they are data structur ...
- [Java] 读取文件
1.按字节读取文件内容2.按字符读取文件内容3.按行读取文件内容 4.随机读取文件内容 public class ReadFromFile { /** * 以字节为单位读取文件,常用于读二进制文件,如 ...
- 【CQOI2009】中位数图
[题目链接] 点击打开链接 [算法] 将小于m的数看作-1,大于m的看作1 然后求前缀和,如果区间[l,r]的中位数是m,显然有 : sum(r) - sum(l-1) = 0 因此,只需m的位置之前 ...
- 【SDOI2012】 Longgue的问题
[题目链接] 点击打开链接 [算法] gcd(i,n)是n的约数 不妨设gcd(i,n) = d 考虑枚举d和gcd(i,n) = d有多少个 gcd(i,n) = d gcd(i/d,n/d) = ...