hdu3966 树链剖分点权模板+线段树区间更新/树状数组区间更新单点查询
点权树的模板题,另外发现树状数组也是可以区间更新的。。
注意在对链进行操作时方向不要搞错
线段树版本
#include<bits/stdc++.h>
using namespace std;
#define maxn 50005
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
struct Edge{int to,next;}edge[maxn<<];
int a[maxn],head[maxn],tot;
int deep[maxn],fa[maxn],son[maxn],num[maxn];
int top[maxn],fp[maxn],p[maxn],pos;
inline void addedge(int u,int v){edge[tot].to=v;edge[tot].next=head[u];head[u]=tot++;}
void dfs1(int u,int pre,int dep){
fa[u]=pre;deep[u]=dep;num[u]=;
for(int i=head[u];i!=-;i=edge[i].next){
int v=edge[i].to;
if(v==pre) continue;
dfs1(v,u,dep+);
num[u]+=num[v];
if(son[u]==- || num[son[u]]<num[v]) son[u]=v;
}
}
void getpos(int u,int sp){
top[u]=sp;p[u]=pos++;fp[p[u]]=u;
if(son[u]==-) return;
getpos(son[u],sp);
for(int i=head[u];i!=-;i=edge[i].next){
int v=edge[i].to;
if(v!=fa[u] && v!=son[u]) getpos(v,v);
}
} int seg[maxn<<];
void build(int l,int r,int rt){
seg[rt]=;
if(l==r) {seg[rt]=a[fp[l]];return;}//注意这里,线段树上坐标为i的点权值是第i个被访问到的点的权值
int m=l+r>>;
build(lson);build(rson);
}
inline void pushdown(int rt){
if(seg[rt]) {
seg[rt<<]+=seg[rt];
seg[rt<<|]+=seg[rt];
seg[rt]=;
}
}
void update(int L,int R,int c,int l,int r,int rt){
if(L<=l && R>=r){seg[rt]+=c;return;}
pushdown(rt);
int m=l+r>>;
if(L<=m) update(L,R,c,lson);
if(R>m) update(L,R,c,rson);
}
int query(int pos,int l,int r,int rt){
if(l==r) return seg[rt];
pushdown(rt);
int m=l+r>>;
if(pos<=m) return query(pos,lson);
else return query(pos,rson);
}
void change(int u,int v,int c){
int f1=top[u],f2=top[v];
while(f1!=f2){
if(deep[f1]<deep[f2]){swap(u,v);swap(f1,f2);}
update(p[f1],p[u],c,,pos,);
u=fa[f1];f1=top[u];
}
if(deep[u]>deep[v]) swap(u,v);
update(p[u],p[v],c,,pos,);
}
void init(){
tot=pos=;pos=;
memset(head,-,sizeof head);
memset(son,-,sizeof son);
}
int main(){
int n,m,q,u,v,k;
while(scanf("%d%d%d",&n,&m,&q)==){
init();
for(int i=;i<=n;i++)scanf("%d",&a[i]);
for(int i=;i<=m;i++){scanf("%d%d",&u,&v);addedge(u,v);addedge(v,u);}
dfs1(,,);getpos(,);build(,pos,);
char op[];
while(q--){
scanf("%s",op);
if(op[]=='I') {scanf("%d%d%d",&u,&v,&k);change(u,v,k);}
else if(op[]=='D'){scanf("%d%d%d",&u,&v,&k);change(u,v,-k);}
else {scanf("%d",&u);printf("%d\n",query(p[u],,pos,));}
}
}
}
树状数组版本。。果然还是树状数组快一点啊
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define MAXN 50010
using namespace std;
struct Edge{
int to, next;
}edge[MAXN*];
int head[MAXN], tot;
int deep[MAXN];
int fa[MAXN];
int son[MAXN];
int p[MAXN];
int fp[MAXN];
int top[MAXN];
int num[MAXN];
int pos;
int c[MAXN], n;//树状数组的
void init()
{
tot=;
memset(head,-,sizeof(head));
pos=;//树状数组,编号从1开始
memset(son,-,sizeof(son));
memset(c,,sizeof(c));
}
void addedge(int u,int v)
{
edge[tot].to=v;edge[tot].next=head[u];head[u]=tot++;
}
void dfs1(int u, int pre, int d){
deep[u] = d;
fa[u] = pre;
num[u] = ;
for(int i = head[u]; i != -; i = edge[i].next){
int v = edge[i].to;
if (v != pre){//v不能是父节点
dfs1(v, u, d+);
num[u] += num[v];
if (son[u]==-||num[v]>num[son[u]])
son[u] = v;
}
}
}
void getpos(int u, int sp){
top[u] = sp;
p[u] = pos++;
fp[p[u]] = u;
if (son[u] == -)
return;
getpos(son[u], sp);
for(int i = head[u]; i != -; i = edge[i].next){
int v = edge[i].to;
if (v != fa[u] && v != son[u])
getpos(v, v);
}
} //树状数组
int lowbit(int i){
return i&(-i);
}
int sum(int i){
int s = ;
while(i<=n){
s += c[i];
i +=lowbit(i);
}
return s;
}
void add(int i, int val){
while(i>){
c[i]+=val;
i-=lowbit(i);
}
}
void change(int u, int v, int val){
int f1 = top[u], f2 = top[v];
while(f1 != f2){
if (deep[f1]<deep[f2]){
swap(f1, f2);
swap(u, v);
}
add(p[u], val);//树状数组的区间更新原理
add(p[f1]-, -val);//这儿得减去一个东西
u = fa[f1];
f1 = top[u];
}
if(deep[u]>deep[v])
swap(u,v);//默认u是v的祖先
add(p[u]-, -val);
add(p[v], val);
}
int a[MAXN];
int main(){
int M, P;
while(~scanf("%d%d%d", &n, &M, &P)){
int u, v;
int C1, C2, K;
char op[];
init();
for(int i = ; i<=n; i++)
scanf("%d", &a[i]);
while(M--){
scanf("%d%d", &u, &v);
addedge(u, v);
addedge(v, u);
}
dfs1(, , );
getpos(, );
while(P--){
scanf("%s", op);
if (op[]=='Q'){
scanf("%d", &u);
printf("%d\n", sum(p[u])+a[u]);
}
else {
scanf("%d%d%d", &C1, &C2, &K);
if (op[]=='D')
K = -K;
change(C1, C2, K);
}
}
}
}
hdu3966 树链剖分点权模板+线段树区间更新/树状数组区间更新单点查询的更多相关文章
- 树链剖分边权模板spoj375
树链剖分是树分解成多条链来解决树上两点之间的路径上的问题 如何求出树链:第一次dfs求出树上每个结点的大小和深度和最大的儿子,第二次dfs就能将最大的儿子串起来并hash(映射)到线段树上(或者其他数 ...
- 刷题总结——骑士的旅行(bzoj4336 树链剖分套权值线段树)
题目: Description 在一片古老的土地上,有一个繁荣的文明. 这片大地几乎被森林覆盖,有N座城坐落其中.巧合的是,这N座城由恰好N-1条双 向道路连接起来,使得任意两座城都是连通的.也就是说 ...
- 计蒜客 38229.Distance on the tree-1.树链剖分(边权)+可持久化线段树(区间小于等于k的数的个数)+离散化+离线处理 or 2.树上第k大(主席树)+二分+离散化+在线查询 (The Preliminary Contest for ICPC China Nanchang National Invitational 南昌邀请赛网络赛)
Distance on the tree DSM(Data Structure Master) once learned about tree when he was preparing for NO ...
- BZOJ 1036 [ZJOI2008]树的统计Count (树链剖分 - 点权剖分 - 单点权修改)
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1036 树链剖分模版题,打的时候注意点就行.做这题的时候,真的傻了,单词拼错检查了一个多小时 ...
- Luogu 2590 [ZJOI2008]树的统计 / HYSBZ 1036 [ZJOI2008]树的统计Count (树链剖分,LCA,线段树)
Luogu 2590 [ZJOI2008]树的统计 / HYSBZ 1036 [ZJOI2008]树的统计Count (树链剖分,LCA,线段树) Description 一棵树上有n个节点,编号分别 ...
- 【bzoj4999】This Problem Is Too Simple! 树链剖分+动态开点线段树
题目描述 给您一颗树,每个节点有个初始值. 现在支持以下两种操作: 1. C i x(0<=x<2^31) 表示将i节点的值改为x. 2. Q i j x(0<=x<2^31) ...
- POJ3237 Tree 树链剖分 边权
POJ3237 Tree 树链剖分 边权 传送门:http://poj.org/problem?id=3237 题意: n个点的,n-1条边 修改单边边权 将a->b的边权取反 查询a-> ...
- Qtree3题解(树链剖分(伪)+线段树+set)
外话:最近洛谷加了好多好题啊...原题入口 这题好像是SPOJ的题,挺不错的.看没有题解还是来一篇... 题意: 很明显吧.. 题解: 我的做法十分的暴力:树链剖分(伪)+线段树+\(set\)... ...
- POJ2763 Housewife Wind 树链剖分 边权
POJ2763 Housewife Wind 树链剖分 边权 传送门:http://poj.org/problem?id=2763 题意: n个点的,n-1条边,有边权 修改单边边权 询问 输出 当前 ...
随机推荐
- Linux发行版Debian操作系统破译密码
Linux发行版Debian操作系统破译密码 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 其实玩过Linux的小伙伴,对破解服务器密码都应该有所了解,典型的两个代表,我觉得一个是 ...
- 学习windows编程 day6 之处理鼠标移动
#define POINT_MAX 1000 LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPara ...
- git commit 时出现:please enter the commit message for your changes
每次准备提交前,先用 git status 看下,是不是都已暂存起来了,然后再运行提交命令 git commit: $ git commit 这种方式会启动文本编辑器以便输入本次提交的说明.(默认会启 ...
- centos7安装telnet
yum list |grep telnet yum install telnet.x86_64 安装后再测试
- Kettle 中转换(transformation)的执行过程
1,Spoon.java的main方法是整个Kettle运行的入口.当打开Kettle的设计器界面后,可以在其中设计作业和转换.这里讨论转换的执行过程. 2,设计好一个转换后,转换保存的本地文件是 . ...
- Scapy Fuzz实现——S7协议从建连到“正常交流“(一)
转载:安全客 酝酿了“三秒钟“,准备理清逻辑写写我学习的心得,自认为和Siemens S7协议有过一段时间浅浅的“交流”,所以这过程中涉及到了自己整理的自认为有用的东西,涉及工具.脚本这般,发出来让大 ...
- C++中模板的使用
为什么使用模板: C++重载(overloading),重载函数一般含有不同的参数个数或不同的参数类型.如果使用MAX函数对不同类型的求最大值,就要定义不同的重载函数: int max(int x,i ...
- position属性absolute与relative 的区别
连接:https://www.cnblogs.com/duyanli/p/3534005.html 每次要用到Position属性时,总要去搜索下,这两个属性值的区别:今天就直接复制网上的结果,以便以 ...
- Python(十) Python 中的 *args 和 **kwargs
转载:团子的小窝 http://kodango.com/variable-arguments-in-python
- QT中QString 与 int float double 等类型的相互转换
Qt中 int ,float ,double转换为QString 有两种方法 1.使用 QString::number(); 如: long a = 63; QString s = QString:: ...