点权树的模板题,另外发现树状数组也是可以区间更新的。。

注意在对链进行操作时方向不要搞错

线段树版本

#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 树链剖分点权模板+线段树区间更新/树状数组区间更新单点查询的更多相关文章

  1. 树链剖分边权模板spoj375

    树链剖分是树分解成多条链来解决树上两点之间的路径上的问题 如何求出树链:第一次dfs求出树上每个结点的大小和深度和最大的儿子,第二次dfs就能将最大的儿子串起来并hash(映射)到线段树上(或者其他数 ...

  2. 刷题总结——骑士的旅行(bzoj4336 树链剖分套权值线段树)

    题目: Description 在一片古老的土地上,有一个繁荣的文明. 这片大地几乎被森林覆盖,有N座城坐落其中.巧合的是,这N座城由恰好N-1条双 向道路连接起来,使得任意两座城都是连通的.也就是说 ...

  3. 计蒜客 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 ...

  4. BZOJ 1036 [ZJOI2008]树的统计Count (树链剖分 - 点权剖分 - 单点权修改)

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1036 树链剖分模版题,打的时候注意点就行.做这题的时候,真的傻了,单词拼错检查了一个多小时 ...

  5. Luogu 2590 [ZJOI2008]树的统计 / HYSBZ 1036 [ZJOI2008]树的统计Count (树链剖分,LCA,线段树)

    Luogu 2590 [ZJOI2008]树的统计 / HYSBZ 1036 [ZJOI2008]树的统计Count (树链剖分,LCA,线段树) Description 一棵树上有n个节点,编号分别 ...

  6. 【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) ...

  7. POJ3237 Tree 树链剖分 边权

    POJ3237 Tree 树链剖分 边权 传送门:http://poj.org/problem?id=3237 题意: n个点的,n-1条边 修改单边边权 将a->b的边权取反 查询a-> ...

  8. Qtree3题解(树链剖分(伪)+线段树+set)

    外话:最近洛谷加了好多好题啊...原题入口 这题好像是SPOJ的题,挺不错的.看没有题解还是来一篇... 题意: 很明显吧.. 题解: 我的做法十分的暴力:树链剖分(伪)+线段树+\(set\)... ...

  9. POJ2763 Housewife Wind 树链剖分 边权

    POJ2763 Housewife Wind 树链剖分 边权 传送门:http://poj.org/problem?id=2763 题意: n个点的,n-1条边,有边权 修改单边边权 询问 输出 当前 ...

随机推荐

  1. GO语言的进阶之路-go的程序结构以及包简介

    GO语言的进阶之路-go的程序结构以及包简介 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.编辑,编译和运行 A,编辑 Go程序使用UTF-8编码的纯Unicode文本编写.大 ...

  2. xen 配置vm 跟随xen server一起启动

    查看Xen Server 信息 (1)查看pool信息 [root@xenserver-243 ~]# xe pool-list uuid ( RO) : e29037aa-0dca-f95a-193 ...

  3. Study 6 —— 字体和段落属性

    字体风格{font-style:normal | italic | oblique | inherit字体复合属性{font:font-style font-variant font-weight f ...

  4. Struts2_day04

    一.回顾 1什么是值栈 (1)action和servlet区别 2 如何获取值栈对象 3 值栈内部结构 (1)root和context 4 向值栈放数据 (1)向值栈放字符串 (2)向值栈放对象 (3 ...

  5. golang string int int64转换

    #string到int int,err:=strconv.Atoi(string) #string到int64 int64, err := strconv.ParseInt(string, 10, 6 ...

  6. 电脑爱好——PE系统分区工具 分区时函数错误,报000000001错误 解决方法

    1.启动硬盘分区软件diskgenius(一般都是这个分区软件,这个PE系统自带的居多) 2.将现有的分区全部删掉 3.选择菜单栏——“硬盘”——“转换分区表类型为MBR格式”——转换完成 4.快速分 ...

  7. hadoop HA 配置 + zookeeper 服务注册

    环境测试 6台机器 centos6.7 x64 master ( namenode/cluster ) 10.10.100.101 namenode1 10.10.100.105 namenode2 ...

  8. Nginx PHP支持

    Nginx 支持 PHP server { server_name www.www1.com www1.com; location / { index index.php index.html; ro ...

  9. B - Internship (网络流关键割边)

    题目链接:https://cn.vjudge.net/contest/281961#problem/B 题目大意:给你n个城市,中间有一些中转站,然后给你终点,再给你l条轨道以及流量,问你增加哪几条轨 ...

  10. jquery中选择checkbox拼接成字符串,然后到后台拆分取值

    jquery中选择checkbox拼接成字符串,然后到后台拆分取值 js中的代码 $("#btn").click(function(){ var chenked=$("i ...