HDU 3966 (树链剖分+线段树)
Problem Aragorn's Story (HDU 3966)
题目大意
给定一颗树,有点权。
要求支持两种操作,将一条路径上的所有点权值增加或减少ai,询问某点的权值。
解题分析
树链剖分模板题。
实质上树链剖分进行了点对点的一次映射,保证了重链上的点在线段树上的位置是连续的。
树链剖分的两个性质(转):
性质1:如果(v,u)为轻边,则siz[u] * 2 < siz[v];
性质2:从根到某一点的路径上轻链、重链的个数都不大于logn。
保证了一个区间的时间复杂度是log2(n)。
要分清3种标号含义(易混) :树中节点标号,树中节点对应线段树中位置标号,线段树中区间标号。
树链剖分相关数组意义 :
size[i] :以i为根的子树的大小
fa[i] :i节点的父亲
dep[i] :i节点的深度
son[i] :i节点的重儿子(所有儿子中size最大的)
w[i] :i节点在线段树中对应的位置
top[i] :i节点所在重链的顶端节点,若为轻链,则为自身。
rank[i] :线段树中所对应树中节点。
参考程序
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath> #define V 50008
#define E 100008
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1 int n,m,Q;
int a[V],size[V],dep[V],fa[V],top[V],w[V],son[V],rank[V];
int sum[V << ],lazy[V << ]; struct line{
int u,v,nt;
}eg[E];
int lt[V],summ,cnt; void adt(int u,int v){
eg[++summ].u=u; eg[summ].v=v; eg[summ].nt=lt[u]; lt[u]=summ;
} void add(int u,int v){
adt(u,v); adt(v,u);
} void dfs1(int u){
size[u]=; son[u]=;
for (int i=lt[u];i;i=eg[i].nt){
int v=eg[i].v;
if (v!=fa[u]){
fa[v]=u;
dep[v]=dep[u]+;
dfs1(v);
size[u]+=size[v];
if (size[v]>size[son[u]]) son[u]=v;
}
}
} void dfs2(int u,int tp,int x){
top[u]=tp; w[u]=++cnt; rank[cnt]=u;
if (son[u]) dfs2(son[u],tp,);
for (int i=lt[u];i;i=eg[i].nt){
int v=eg[i].v;
if (v==son[u] || v==fa[u]) continue;
dfs2(v,v,);
}
} void init(){
memset(lt,,sizeof(lt));
summ=; cnt=;
for (int i=;i<=n;i++) scanf("%d",&a[i]);
for (int i=;i<=m;i++){
int u,v;
scanf("%d %d",&u,&v);
add(u,v);
}
dep[]=; fa[]=;
dfs1();
dfs2(,,);
} void pushup(int rt){
sum[rt]=sum[rt<<]+sum[rt<<|];
} void pushdown(int rt,int m){
if (lazy[rt]){
lazy[rt<<]+=lazy[rt];
lazy[rt<<|]+=lazy[rt];
sum[rt<<]+=lazy[rt]*(m-m / );
sum[rt<<|]+=lazy[rt]*(m / );
lazy[rt]=;
}
} void build(int l,int r,int rt){
lazy[rt]=;
if (l==r){
sum[rt]=a[rank[l]];
return;
}
int m=(l+r)/;
build(lson);
build(rson);
pushup(rt);
} void update(int L,int R,int val,int l,int r,int rt){
if (L<=l && r<=R){
sum[rt]+=val*(r-l+);
lazy[rt]+=val;
return;
}
pushdown(rt,r-l+);
int m=(l+r)>>;
if (L<=m) update(L,R,val,lson);
if (m< R) update(L,R,val,rson);
pushup(rt);
} int query(int x,int l,int r,int rt){
if (l==r){
return sum[rt];
}
pushdown(rt,r-l+);
int m=(l+r)>>;
if (x<=m) return query(x,lson);
if (m< x) return query(x,rson);
} void change(int x,int y,int val){
while (top[x]!=top[y]){
if (dep[top[x]]<dep[top[y]]) std::swap(x,y);
update(w[top[x]],w[x],val,,n,);
x=fa[top[x]];
}
if (dep[x]>dep[y]) std::swap(x,y);
update(w[x],w[y],val,,n,);
} int main(){
while (~scanf("%d %d %d",&n,&m,&Q)){
init();
build(,n,);
while (Q--){
char s[];
int x,y,z;
scanf("%s",s);
if (s[]=='I'){
scanf("%d %d %d",&x,&y,&z);
change(x,y,z);
}
if (s[]=='D'){
scanf("%d %d %d",&x,&y,&z);
change(x,y,-z);
}
if (s[]=='Q'){
scanf("%d",&x);
printf("%d\n",query(w[x],,n,));
}
}
}
}
HDU 3966 (树链剖分+线段树)的更多相关文章
- HDU 2460 Network(双连通+树链剖分+线段树)
HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链 ...
- Aragorn's Story 树链剖分+线段树 && 树链剖分+树状数组
Aragorn's Story 来源:http://www.fjutacm.com/Problem.jsp?pid=2710来源:http://acm.hdu.edu.cn/showproblem.p ...
- 【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 ...
随机推荐
- IO流--复制picture ,mp3
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileInputStream; import ...
- BOM组件物料重复检查
好吧,今天同事让做个BOM组件物料重复检查 网上有很多例子都是在保存的时候检查的,用的是BADI :BOM_UPDATE 自己也试了一下,麻烦....很麻烦...尤其是在重复检查的时候: METHOD ...
- jquery mobile 请求数据方法执行时显示加载中提示框
在jquery mobile开发中,经常需要调用ajax方法,异步获取数据,如果异步获取数据方法由于网速等等的原因,会有一个反应时间,如果能在点击按钮后数据处理期间,给一个正在加载的提示,客户体验会更 ...
- (巨坑)改了tpl文件之后,前端效果没反应
通常前端修改很小的部分代码,并不会立即显示出效果.比如,原来是 ,修改后是 虽然只是加多了一个函数,但是作用很大,这种情况下,可能是由于浏览器缓存的原因,修改后的代码没有被重新加载.这个时候,只需要在 ...
- String.equals()方法的实现代码,
通常对String的比较有两种情况,一个是使用==,另一个是使用equals()方法,注意==是对对象的地址进行比较的,而String中的equals()方法是覆盖了Object类的方法,并且实现为对 ...
- BZOJ1576 [Usaco2009 Jan]安全路经Travel
首先用Dijkstra做出最短路生成树,设dis[p]为1到p点的最短路长度 对于一条不在生成树上的边u -> v,不妨设fa为u.v的lca 则一fa到v的路径上的任意点x都可以由u达到,走的 ...
- PDF 补丁丁 0.4.1.820 测试版发布:统一PDF的页面尺寸
之前删掉了统一页面尺寸功能,在这个版本给搬回来了. 调整页面留白的功能还没实现,请无视相关选项.
- 基于Storm的工程中使用log4j
最近使用Storm开发,发现log4j死活打不出debug级别的日志,网上搜到的关于log4j配置的方法都试过了,均无效. 最终发现问题是这样的:最新的storm使用的日志系统已经从log4j切换到了 ...
- 【bzoj2281】[Sdoi2011]黑白棋
博弈论---Nimk问题. dp再搞搞. 很容易看出,该游戏的终态是每两个棋子都紧靠着.当一颗棋子移动,另一方与该棋子对应的那一刻可以立即追上,使得仍旧紧靠,最终棋子动弹不得,游戏结束. 还能看出,对 ...
- Android 解压html压缩数据
public static String unzipHTML(String s){ int endPos = s.indexOf("\r\n\r\n"); if(endPos< ...