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条边,有边权 修改单边边权 询问 输出 当前 ...
随机推荐
- 运用Zabbix实现内网服务器状态及局域网状况监控(2) —— 环境配置
一.基本要求 Zabbix支持如下操作系统: LinuxIBM AIXFreeBSDNetBSDOpenBSDHP-UXMac OS XSolarisWindows: 2000, Server 200 ...
- 源码分析之CountDownLatch
https://www.cnblogs.com/leesf456/p/5406191.html
- POJ - 1905 Expanding Rods(二分+计算几何)
http://poj.org/problem?id=1905 题意 一根两端固定在两面墙上的杆,受热后变弯曲.求前后两个状态的杆的中点位置的距离 分析 很明显需要推推公式. 由②的限制条件来二分角度, ...
- Hammer.js 移动端手势库,多点触控插件
jquery用法: 引入3个JS:<script src="jquery.js"></script> <script src="hammer ...
- 在ASP.Net环境中,当用户点击报表中的超链接时如何调用Java Script方法?
问题描述:在ASP.Net环境中,当用户点击报表中的超链接时如何调用Java Script方法? 问题解答: 你可以在TextObject.Hyperlink对象中编写js代码(javascript: ...
- luogu P3576 [POI2014]MRO-Ant colony
传送门 一群蚂蚁能被吃,也就是走到指定边的两端点之一要走到另一端点时有\(k\)只,我们可以从这两端点逆推,记两个值为走到某个点时最后会被吃掉\(k\)只蚂蚁的蚂蚁数量范围,式子下面有,很好理解(雾) ...
- Activity Window View WindowManager关系&Touch事件分发机制
http://www.cnblogs.com/linjzong/p/4191891.html https://www.cnblogs.com/kest/p/5141817.html https://b ...
- jQuery——Js与jQuery的相互转换
$()与jQuery() jQuery中$函数,根据传入参数的不同,进行不同的调用,实现不同的功能.返回的是jQuery对象 jQuery这个js库,除了$之外,还提供了另外一个函数:jQuery j ...
- FPN 学习笔记
通常,利用网络对物体进行检测时,浅层网络分辨率高,学到的是图片的细节特征,深层网络,分辨率低,学到的更多的是语义特征. 1).通常的CNN使用如下图中显示的网络,使用最后一层特征图进行预测 例如VGG ...
- 【逆向工具】IDA使用6-签名文件制作
0x1 签名文件制作的方法: 找到静态编译的程序库 使用IDA中的fair工具包,对静态库操作,生成特征库(IDA6.8 是flair68.zip) 0x2 步骤 第一步:使用pcf生成对应静态库的p ...