/**
problem: http://acm.hdu.edu.cn/showproblem.php?pid=3966
裸板
**/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<vector>
using namespace std; const int MAXN = ; template <typename T>
class SegmentTree {
private:
struct Node {
int left, right;
T sum, lazy;
} node[MAXN << ];
T data[MAXN];
void pushUp(int root) {
node[root].sum = node[root << ].sum + node[root << | ].sum;
}
void pushDown(int root) {
if(node[root].left == node[root].right) return;
int lson = root << ;
int rson = root << | ;
node[lson].sum += node[root].lazy * (node[lson].right - node[lson].left + );
node[rson].sum += node[root].lazy * (node[rson].right - node[rson].left + );
node[lson].lazy += node[root].lazy;
node[rson].lazy += node[root].lazy;
node[root].lazy = ;
}
public:
void build(int left, int right, int root = ) {
node[root].left = left;
node[root].right = right;
node[root].lazy = ;
if(left == right) {
node[root].sum = data[left];
} else {
int mid = (left + right) >> ;
build(left, mid, root << );
build(mid + , right, root << | );
pushUp(root);
}
}
void update(int left, int right, T value, int root = ) {
int lson = root << ;
int rson = root << | ;
node[root].sum += value * (right - left + );
if(node[root].left == left && node[root].right == right) {
node[root].lazy += value;
return ;
}
if(left >= node[rson].left) {
update(left, right, value, rson);
} else if(right <= node[lson].right) {
update(left, right, value, lson);
} else {
update(left, node[lson].right, value, lson);
update(node[rson].left, right, value, rson);
}
}
T query(int left, int right, int root = ) {
int lson = root << ;
int rson = root << | ;
if(node[root].lazy) pushDown(root);
if(node[root].left == left && node[root].right == right) {
return node[root].sum;
}
if(left >= node[rson].left) {
return query(left, right, rson);
} else if(right <= node[lson].right) {
return query(left, right, lson);
} else {
return query(left, node[lson].right, lson) + query(node[rson].left, right, rson);
}
}
void clear(int n, const vector<int> &d) {
for(int i = ; i <= n; i ++) {
this->data[i] = d[i];
}
build(, n);
}
}; template <typename T>
class TreeToLink {
private:
struct Point {
int size, son, depth, father, top, newId;
T data;
} point[MAXN];
struct Edge {
int to, next;
} edge[MAXN << ];
int oldId[MAXN], first[MAXN], sign, sumOfPoint, cnt;
SegmentTree<T> st;
void dfs1(int u, int father = , int depth = ) {
point[u].depth = depth;
point[u].father = father;
point[u].size = ;
int maxson = -;
for(int i = first[u]; i != -; i = edge[i].next) {
int to = edge[i].to;
if(to == father) continue;
dfs1(to, u, depth + );
point[u].size += point[to].size;
if(point[to].size > maxson) {
point[u].son = to;
maxson = point[to].size;
}
}
}
void dfs2(int u, int top) {
point[u].newId = ++cnt;
oldId[cnt] = u;
point[u].top = top;
if(point[u].son == -) {
return ;
}
dfs2(point[u].son, top);
for(int i = first[u]; i != -; i = edge[i].next) {
int to = edge[i].to;
if(to == point[u].son || to == point[u].father) continue;
dfs2(to, to);
}
}
public:
void clear(int n) {
sumOfPoint = n;
sign = ;
cnt = ;
for(int i = ; i <= n; i ++) {
first[i] = -;
point[i].son = -;
scanf("%d", &point[i].data);
}
}
void addEdgeOneWay(int u, int v) {
edge[sign].to = v;
edge[sign].next = first[u];
first[u] = sign ++;
}
void addEdgeTwoWay(int u, int v) {
addEdgeOneWay(u, v);
addEdgeOneWay(v, u);
}
void preWork(int x = ) {
dfs1(x);
dfs2(x, x);
vector<int> data(sumOfPoint + );
for(int i = ; i <= sumOfPoint; i ++) {
data[i] = point[oldId[i]].data;
}
st.clear(sumOfPoint, data);
}
void updatePath(int x, int y, T z){
while(point[x].top != point[y].top){
if(point[point[x].top].depth < point[point[y].top].depth)
swap(x, y);
st.update(point[point[x].top].newId, point[x].newId, z);
x = point[point[x].top].father;
}
if(point[x].depth > point[y].depth)
swap(x, y);
st.update(point[x].newId, point[y].newId, z);
}
T queryPath(int x, int y){
T ans = ;
while(point[x].top != point[y].top){
if(point[point[x].top].depth < point[point[y].top].depth)
swap(x, y);
ans += st.query(point[point[x].top].newId, point[x].newId);
x = point[point[x].top].father;
}
if(point[x].depth > point[y].depth)
swap(x, y);
ans += st.query(point[x].newId, point[y].newId);
return ans;
}
void updateSon(int x, T z){
st.update(point[x].newId, point[x].newId + point[x].size - , z);
}
T querySon(int x){
return st.query(point[x].newId, point[x].newId + point[x].size - );
}
T queryPoint(int x) {
return queryPath(x, x);
}
void updatePoint(int x, T z) {
updatePath(x, x, z);
}
}; class Solution {
private:
int n, m, p;
TreeToLink<int> ttl;
public:
void solve() {
while(~scanf("%d%d%d", &n, &m, &p)){
ttl.clear(n);
for(int i = , a, b; i < m; i ++) {
scanf("%d%d", &a, &b);
ttl.addEdgeTwoWay(a, b);
}
ttl.preWork();
while(p --) {
char opt;
int a, b, c;
scanf(" %c%d", &opt, &a);
if(opt == 'I') {
scanf("%d%d", &b, &c);
ttl.updatePath(a, b, c);
} else if(opt == 'D') {
scanf("%d%d", &b, &c);
ttl.updatePath(a, b, -c);
} else if(opt == 'Q') {
printf("%d\n", ttl.queryPoint(a));
}
}
}
}
} DarkScoCu; int main() {
DarkScoCu.solve();
return ;
}

hdu 3966 Aragorn's Story : 树链剖分 O(nlogn)建树 O((logn)²)修改与查询的更多相关文章

  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 树链剖分 按点

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

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

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

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

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

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

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

随机推荐

  1. HDU 5011 NIM博弈

    http://www.cnblogs.com/exponent/articles/2141477.html http://acm.hust.edu.cn/vjudge/contest/122814#p ...

  2. python私有成员

    在一个模块中,我们可能会定义很多函数和变量,但有的函数和变量我们希望给别人使用,有的函数和变量我们希望仅仅在模块内部使用.在Python中,是通过_前缀来实现的. 正常的函数和变量名是公开的(publ ...

  3. Android基础Activity篇——创建一个活动(Activity)

    1.创建活动 首先用AS创建一个add no activity项目名使用ActivityTest,包名为默认的com.example.activitytest 2.右击app.java.com.exa ...

  4. Hadoop ->> HIVE

    HIVE的由来: 最初由Facebook基于HDFS开发出来的一套数据仓库工具. HIVE可以干什么? HIVE可以将已经结构化的数据映射成一张表,然后可以使用HIVE语言像写T-SQL一样查询数据. ...

  5. docker 部署 nginx+php+mysql

    系统:centos7 使用root账户 开放80端口 firewall-cmd --zone=public --add-port=80/tcp --permanent 安装docker yum ins ...

  6. 什么是SWP文件?能否删除swp文件?

    SWP意思就是交换文件..SWP是各种操作系统(Windows或Linux)使用的交换文件的文件扩展名. 可以安全地清理SWP文件以释放磁盘空间. 要清理SWP文件,请按照以下步骤操作: 运行WinU ...

  7. 学习和运用scrum

    作为长大的大三老腊肉,我们已经在长大生活了两年多,对于什么是长大人最想完善的校园需求.最想拥有的校园服务媒介也有了更加深切的体会. 于是,GoodJob小团队blingbling闪现啦!! GoodJ ...

  8. python入门15 函数

    函数的主要作用是实现代码复用 1 python内置函数 2 匿名函数lambda 3 自定义函数 def functionname(arg):... #coding:utf-8 #/usr/bin/p ...

  9. 使用ToDateTime方法转换日期显示格式

    实现效果: 知识运用: Convert类的ToDateTime方法:(将字符串转化为DateTime对象) public static DateTime ToDateTime(string value ...

  10. 【转】iOS保持界面流畅的技巧

    原文链接:iOS保持界面流畅的技巧 这篇文章会非常详细的分析 iOS 界面构建中的各种性能问题以及对应的解决思路,同时给出一个开源的微博列表实现,通过实际的代码展示如何构建流畅的交互. Index演示 ...