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条边,有边权 修改单边边权 询问 输出 当前 ...
随机推荐
- js位操作
1.&(与) 都是1才是1 例如:14&15 (14 二进制 1110 15 二进制 1111 &与的结果 1110 ---->结果14) (14& ...
- Python基础【day01】:Hello World程序(二)
本节内容 安装 Hello World程序 变量 一.Python安装 windows 1 2 3 4 5 6 7 1.下载安装包 https://www.python.org/downloa ...
- zabbix微信预警出现的问题
系统环境:centos7.3 zabbix_server: 3.0.3 3.0.6 问题描述 zabbix预警突然不能发送微信,需要修复 排查步骤 1. 检查微信企业平台应用的key是否过期,结果没过 ...
- 【1】【JUC】Condition和生产者消费者模型
本篇文章将介绍Condition的实现原理和基本使用方法,基本过程如下: 1.Condition提供了await()方法将当前线程阻塞,并提供signal()方法支持另外一个线程将已经阻塞的线程唤醒. ...
- 拖放排序插件Sortable.js 兼容好及功能全个人觉得比dragula.js 好的多
经测试,Sortable.js 兼容好和使用方便都是比较不错的,特别手机端使用很棒 介绍 Sortable.js是一款轻量级的拖放排序列表的js插件(虽然体积小,但是功能很强大)下载地址:https: ...
- IDEA不生成WAR包,报错
com.intellij.javaee.oss.admin.jmx.JmxAdminException: com.intellij.execution.ExecutionExceptionProjec ...
- PHP 将amr音频文件转换为mp3格式
说下整体思路 1.服务器安装ffmpeg 2.使用ffmpeg -i 指令来转换amr为mp3格式(这个到时候写在PHP代码中,使用exec函数执行即可) 3.在网页端使用HTML5的audio标签来 ...
- luogu P3924 康娜的线段树
题面传送门 我们可以画图找规律 这里没图,要看图可以去看M_sea dalao的题解(逃 可以发现单个节点\(i\)对答案的贡献为该节点的点权\(*\frac{1}{2^{dep_i}}\)(\(de ...
- MySQL5.7主从复制配置
1 my.cnf文件 配置 binlog_format = ROW log_bin_trust_function_creators=1 log-error = /usr/local/mysql/dat ...
- caffe源码阅读(1)_整体框架和简介(摘录)
原文链接:https://www.zhihu.com/question/27982282 1.Caffe代码层次.回答里面有人说熟悉Blob,Layer,Net,Solver这样的几大类,我比较赞同. ...