Lightoj 1348 Aladdin and the Return Journey (树链剖分)(线段树单点修改区间求和)
Finally the Great Magical Lamp was in Aladdin's hand. Now he wanted to return home. But he didn't want to take any help from the Genie because he thought that it might be another adventure for him. All he remembered was the paths he had taken to reach there. But since he took the lamp, all the genies in the cave became angry and they were planning to attack. As Aladdin was not afraid, he wondered how many genies were there. He summoned the Genie from the lamp and asked this.
Now you are given a similar problem. For simplicity assume that, you are given a tree (a connected graph with no cycles) with n nodes, nodes represent places, edges represent roads. In each node, initially there are an arbitrary number of genies. But the numbers of genies change in time. So, you are given a tree, the number of genies in each node and several queries of two types. They are:
1) 0 i j, it means that you have to find the total number of genies in the nodes that occur in path from node i to j (0 ≤ i, j < n).
2) 1 i v, it means that number of genies in node i is changed to v (0 ≤ i < n, 0 ≤ v ≤ 1000).
Input starts with an integer T (≤ 10), denoting the number of test cases.
Each case starts with a blank line. Next line contains an integer n (2 ≤ n ≤ 30000). The next line contains n space separated integers between 0 and 1000, denoting the number of genies in the nodes respectively. Then there are n-1 lines each containing two integers: u v (0 ≤ u, v < n, u ≠ v) meaning that there is an edge from node u and v. Assume that the edges form a valid tree. Next line contains an integer q (1 ≤ q ≤ 105) followed by q lines each containing a query as described above.
Output
For each case, print the case number in a single line. Then for each query 0 i j, print the total number of genies in the nodes that occur in path i to j.
Sample Input
1
4
10 20 30 40
0 1
1 2
1 3
3
0 2 3
1 1 100
0 2 3
Sample Output
Case 1:
90
170
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <time.h>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#define met(a,b) memset(a,b,sizeof a)
#define pb push_back
#define lson(x) ((x<<1))
#define rson(x) ((x<<1)+1)
using namespace std;
typedef long long ll;
const int N=2e5+;
const int M=N*N+;
int dep[N],siz[N],fa[N],id[N],son[N],val[N],top[N],c[N]; //top 最近的重链父节点
int num,n,m;
vector<int> v[N];
struct tree {
int x,y;
void read() {
scanf("%d%d",&x,&y);
}
};
tree e[N];
void dfs1(int u, int f, int d) {
dep[u] = d;
siz[u] = ;
son[u] = ;
fa[u] = f;
for (int i = ; i < v[u].size(); i++) {
int ff = v[u][i];
if (ff == f) continue;
dfs1(ff, u, d + );
siz[u] += siz[ff];
if (siz[son[u]] < siz[ff])
son[u] = ff;
}
}
void dfs2(int u, int tp) {
top[u] = tp;
id[u] = ++num;
if (son[u]) dfs2(son[u], tp);
for (int i = ; i < v[u].size(); i++) {
int ff = v[u][i];
if (ff == fa[u] || ff == son[u]) continue;
dfs2(ff, ff);
}
} struct Tree {
int l,r,val,sum;
};
Tree tree[*N];
void pushup(int x) {
tree[x].val = max(tree[lson(x)].val, tree[rson(x)].val);
tree[x].sum=tree[lson(x)].sum+tree[rson(x)].sum;
} void build(int l,int r,int v) {
tree[v].l=l;
tree[v].r=r;
if(l==r) {
tree[v].val = val[l];
tree[v].sum=val[l];
return ;
}
int mid=(l+r)>>;
build(l,mid,v*);
build(mid+,r,v*+);
pushup(v);
}
void update(int o,int v,int val) { //log(n)
if(tree[o].l==tree[o].r) {
tree[o].val =tree[o].sum= val;
return ;
}
int mid = (tree[o].l+tree[o].r)/;
if(v<=mid)
update(o*,v,val);
else
update(o*+,v,val);
pushup(o);
}
int querySum(int x,int l,int r) {
if (tree[x].l >= l && tree[x].r <= r) {
return tree[x].sum;
}
int mid = (tree[x].l + tree[x].r) / ;
int ans = ;
if (l <= mid) ans += querySum(lson(x),l,r);
if (r > mid) ans += querySum(rson(x),l,r);
return ans;
}
int Qsum(int u,int v) {
int tp1 = top[u], tp2 = top[v];
int ans = ;
while (tp1 != tp2) {
if (dep[tp1] < dep[tp2]) {
swap(tp1, tp2);
swap(u, v);
}
ans +=querySum(,id[tp1], id[u]);
//printf("ans: %d\n",ans);
u = fa[tp1];
tp1 = top[u];
}
//if (u == v) return ans;
if (dep[u] > dep[v]) swap(u, v);
ans +=querySum(,id[u], id[v]);
return ans;
}
void init(){
for(int i=;i<N;i++)v[i].clear();
met(tree,);met(son,);met(val,);
}
int main() {
int t,T=;
scanf("%d",&t);
while(t--) {
init();
++T;
scanf("%d",&n);
for(int i=; i<=n; i++)scanf("%d",&c[i]);
for(int i=; i<n; i++) {
e[i].read();
e[i].x++;e[i].y++;
v[e[i].x].push_back(e[i].y);
v[e[i].y].push_back(e[i].x);
} num = ;
dfs1(,,);
dfs2(,);
for (int i = ; i <=n; i++) {
val[id[i]] = c[i];
}
build(,num,);
char s[];
scanf("%d",&m);
printf("Case %d:\n",T);
while(m--) {
int o,x,y;
scanf("%d",&o);
scanf("%d%d",&x,&y);
if (o)
x++,update(,id[x],y);
else
x++,y++,printf("%d\n",Qsum(x,y));
}
}
return ;
}
Lightoj 1348 Aladdin and the Return Journey (树链剖分)(线段树单点修改区间求和)的更多相关文章
- 【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 ...
- HDU 2460 Network(双连通+树链剖分+线段树)
HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链 ...
- bzoj2243[SDOI2011]染色 树链剖分+线段树
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 9012 Solved: 3375[Submit][Status ...
随机推荐
- SVN迁移到Git原因说明
1.Git分布式的源码管理 每位开发人员计算机本地会有一份代码库,开发人员可在不受其他人代码提交影响的前提下对源码进行提交/回滚/撤销等操作. 在独立的开发任务中即可实现对源码管理又不受其他开发人员提 ...
- swift中的正则表达式
swift中的t正则表达式 正则表达式是对字符串操作的一种逻辑公式,用事先定义好的一些特定字符.及这些特定字符的组合,组成一个"规则字符串",这个"规则字符串" ...
- Python编码、流程控制、格式化输出
Python编码 初始编码: 电脑的传输,还有储存,实际上都是010101010 ASCII码: (American Standard Code for Information Interchange ...
- python-线程进程与队列
线程,有时被称为轻量级进程,是程序执行流的最小单元线程是程序中一个单一的顺序控制流程.进程内一个相对独立的.可调度的执行单元,是系统独立调度和分派CPU的基本单位指进行中的程序的调度单位.在单个程序中 ...
- 2 27re.py
""" 匹配目标 """ # import re # content = 'Hello 123 4567 World_This is a R ...
- 一个画ROC曲线的封装包
Draw_ROC_Curves This is a python file which is used for drawing ROC curves -f : assign file name -t ...
- HDU 4760 Good Firewall ( Trie树 )
一开始看的时候就想歪了,比赛的时候一直在YY线段树区间覆盖,然后纠结节点数太多开不下怎么办啊啊啊啊…… 然后昨天吃饭的时候也在纠结这到底是个啥题,后来发现公共前缀->前缀??!!!!->这 ...
- Metaspolit
Metaspolit介绍 Metasploit是一款开源的安全漏洞检测工具,安全工作人员常用 Metasploit工具来检测系统的安全性.Metasploit Framework (MSF) 在200 ...
- Linux下nginx支持.htaccess文件实现伪静态的方法!
在Google上搜索的资料很多人都说nginx目前不支持.htaccess文件,我按照nginx的规则试验了一下,结果发现nginx是完全支持.htaccess文件的! 方法如下: 1. 在需要使用. ...
- 【bzoj4974】字符串大师 逆模拟KMP
题目描述 一个串T是S的循环节,当且仅当存在正整数k,使得S是$T^k$(即T重复k次)的前缀,比如abcd是abcdabcdab的循环节.给定一个长度为n的仅由小写字符构成的字符串S,请对于每个k( ...