HDU 3966 Aragorn's Story (树链剖分入门题)
树上路径区间更新,单点查询。
线段树和树状数组都可以用于本题的维护。
线段树:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#define lson rt<<1
#define rson rt<<1|1
#define Lson l,m,lson
#define Rson m+1,r,rson
#define max(a,b) a>b? a:b
using namespace std;
const int maxn =5e4+;
struct Edge{
int to,next;
}E[*maxn];
int n,head[maxn],tot;
int cnt,idx,size[maxn],fa[maxn],son[maxn],dep[maxn],top[maxn],id[maxn],rnk[maxn];
int a[maxn];
struct Node{
int sum,add;
}tree[maxn<<];
void init()
{
cnt=idx=tot=;
memset(head,-,sizeof(head));
dep[]=,fa[]=,size[]=;
memset(son,,sizeof(son));
}
void AddEdge(int u,int v)
{
E[tot] = (Edge){v,head[u]};
head[u]=tot++;
}
void dfs1(int u)
{
size[u]=;
for(int i=head[u];~i;i=E[i].next){
int v=E[i].to;
if(v!=fa[u]){
fa[v]=u;
dep[v]=dep[u]+;
dfs1(v);
size[u]+=size[v];
if(size[son[u]]<size[v]) son[u]=v;
}
}
} void dfs2(int u,int topu)
{
top[u]= topu;
id[u] = ++idx;
rnk[idx] = u;
if(!son[u]) return;
dfs2(son[u],top[u]);
for(int i=head[u];~i;i=E[i].next){
int v=E[i].to;
if(v!=fa[u]&&v!=son[u]) dfs2(v,v);
}
} void pushup(int rt){ tree[rt].sum = tree[lson].sum + tree[rson].sum; } void pushdown(int l,int r,int rt){
if(tree[rt].add){
tree[lson].add += tree[rt].add;
tree[rson].add += tree[rt].add;
int m = (l+r)>>;
tree[lson].sum += (m-l+)*tree[rt].add;
tree[rson].sum += (r-m)*tree[rt].add;
tree[rt].add =;
}
} void build(int l,int r,int rt)
{
tree[rt].add = ;
if(l==r){
tree[rt].sum = a[rnk[l]];
return;
}
int m = (l+r)>>;
build(Lson);
build(Rson);
pushup(rt);
} void update(int L,int R,int v,int l,int r,int rt){
if(L<=l && R>=r){
tree[rt].sum +=(r-l+)*v;
tree[rt].add +=v;
return ;
}
pushdown(l,r,rt);
int m =(l+r)>>;
if(L<=m) update(L,R,v,Lson);
if(R>m) update(L,R,v,Rson);
pushup(rt);
} int query(int p,int l,int r,int rt){ //单点更新
if(l==r) return tree[rt].sum;
pushdown(l,r,rt);
int m = (l+r)>>,ans=;
if(p<=m) ans= query(p,Lson);
else ans =query(p,Rson);
pushup(rt);
return ans;
} void UPDATE(int u,int v,int w)
{
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]]) swap(u,v);
update(id[top[u]],id[u],w,,n,);
u = fa[top[u]];
}
if(dep[u]>dep[v])swap(u,v);
update(id[u],id[v],w,,n,);
} int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
int m,q,u,v;
char op[];
while(scanf("%d%d%d",&n,&m,&q)==){
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();
dfs2(,);
build(,n,);
while(q--){
scanf("%s",op);
if(op[]=='Q'){
scanf("%d",&u);
printf("%d\n",query(id[u],,n,));
}
else{
int w;
scanf("%d%d%d",&u,&v,&w);
if(op[]=='D') w = -w;
UPDATE(u,v,w);
}
}
}
return ;
}
树状数组:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#define lson rt<<1
#define rson rt<<1|1
#define Lson l,m,lson
#define Rson m+1,r,rson
#define max(a,b) a>b? a:b
using namespace std;
const int maxn =5e4+;
struct Edge{
int to,next;
}E[*maxn];
int n,head[maxn],tot;
int idx,size[maxn],fa[maxn],son[maxn],dep[maxn],top[maxn],id[maxn],rnk[maxn];
int a[maxn];
struct Node{
int sum,add;
}tree[maxn<<];
void init()
{
idx=tot=;
memset(head,-,sizeof(head));
dep[]=,fa[]=,size[]=;
memset(son,,sizeof(son));
}
void AddEdge(int u,int v)
{
E[tot] = (Edge){v,head[u]};
head[u]=tot++;
}
void dfs1(int u)
{
size[u]=;
for(int i=head[u];~i;i=E[i].next){
int v=E[i].to;
if(v!=fa[u]){
fa[v]=u;
dep[v]=dep[u]+;
dfs1(v);
size[u]+=size[v];
if(size[son[u]]<size[v]) son[u]=v;
}
}
} void dfs2(int u,int topu)
{
top[u]= topu;
id[u] = ++idx;
rnk[idx] = u; //建树用
if(!son[u]) return;
dfs2(son[u],top[u]);
for(int i=head[u];~i;i=E[i].next){
int v=E[i].to;
if(v!=fa[u]&&v!=son[u]) dfs2(v,v);
}
} void pushup(int rt){ tree[rt].sum = max(tree[lson].sum ,tree[rson].sum); } void pushdown(int l,int r,int rt){
if(tree[rt].add){
tree[lson].add += tree[rt].add;
tree[rson].add += tree[rt].add;
int m = (l+r)>>;
tree[lson].sum += (m-l+)*tree[rt].add;
tree[rson].sum += (r-m)*tree[rt].add;
tree[rt].add =;
}
} void build(int l,int r,int rt)
{
tree[rt].add = ;
if(l==r){
tree[rt].sum = a[rnk[l]];
return;
}
int m = (l+r)>>;
build(Lson);
build(Rson);
pushup(rt);
} void update(int L,int R,int v,int l,int r,int rt){
if(L<=l && R>=r){
tree[rt].sum +=v;
tree[rt].add +=v;
return ;
}
pushdown(l,r,rt);
int m =(l+r)>>;
if(L<=m) update(L,R,v,Lson);
if(R>m) update(L,R,v,Rson);
pushup(rt);
} int query(int p,int l,int r,int rt){ //单点更新
if(l==r) return tree[rt].sum;
pushdown(l,r,rt);
int m = (l+r)>>,ans=;
if(p<=m) ans= query(p,Lson);
else ans =query(p,Rson);
pushup(rt);
return ans;
} int bit[maxn];
void add(int pos,int val){
for(int i=pos;i<=n;i+= i&(-i)) bit[i]+=val;
} inline int sum(int pos){
int res=;
for(int i=pos;i;i-= i&(-i)) res+=bit[i];
return res;
} void UPDATE2(int u,int v,int w) //树状数组维护
{
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]]) swap(u,v);
add(id[top[u]],w);
add(id[u]+,-w);
u = fa[top[u]];
}
if(dep[u]>dep[v]) swap(u,v);
add(id[u],w);
add(id[v]+,-w);
} void UPDATE(int u,int v,int w) //线段树维护
{
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]]) swap(u,v);
update(id[top[u]],id[u],w,,n,);
u = fa[top[u]];
}
if(dep[u]>dep[v])swap(u,v);
update(id[u],id[v],w,,n,);
} int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
int m,q,u,v;
char op[];
while(scanf("%d%d%d",&n,&m,&q)==){
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();
dfs2(,);
//build(1,n,1);
memset(bit,,sizeof(bit));
for(int i=;i<=n;++i){
add(id[i],a[i]);
add(id[i]+,-a[i]);
}
while(q--){
scanf("%s",op);
if(op[]=='Q'){
scanf("%d",&u);
printf("%d\n",sum(id[u]));
//printf("%d\n",query(id[u],1,n,1));
}
else{
int w;
scanf("%d%d%d",&u,&v,&w);
if(op[]=='D') w = -w;
UPDATE2(u,v,w);
//UPDATE(u,v,w);
}
}
}
return ;
}
HDU 3966 Aragorn's Story (树链剖分入门题)的更多相关文章
- HDU 3966 Aragorn's Story(树链剖分)(线段树区间修改)
Aragorn's Story Time Limit: 10000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- HDU 3966 Aragorn's Story 树链剖分+树状数组 或 树链剖分+线段树
HDU 3966 Aragorn's Story 先把树剖成链,然后用树状数组维护: 讲真,研究了好久,还是没明白 树状数组这样实现"区间更新+单点查询"的原理... 神奇... ...
- Hdu 3966 Aragorn's Story (树链剖分 + 线段树区间更新)
题目链接: Hdu 3966 Aragorn's Story 题目描述: 给出一个树,每个节点都有一个权值,有三种操作: 1:( I, i, j, x ) 从i到j的路径上经过的节点全部都加上x: 2 ...
- HDU 3966 Aragorn's Story 树链剖分+BIT区间修改/单点询问
Aragorn's Story Description Our protagonist is the handsome human prince Aragorn comes from The Lord ...
- HDU 3966 Aragorn's Story 树链剖分
Link: http://acm.hdu.edu.cn/showproblem.php?pid=3966 这题注意要手动扩栈. 这题我交g++无限RE,即使手动扩栈了,但交C++就过了. #pragm ...
- hdu 3966 Aragorn's Story : 树链剖分 O(nlogn)建树 O((logn)²)修改与查询
/** problem: http://acm.hdu.edu.cn/showproblem.php?pid=3966 裸板 **/ #include<stdio.h> #include& ...
- hdu 3966 Aragorn's Story 树链剖分 按点
Aragorn's Story Time Limit: 10000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- HDU 3966 Aragorn's Story (树链点权剖分,成段修改单点查询)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3966 树链剖分的模版,成段更新单点查询.熟悉线段树的成段更新的话就小case啦. //树链剖分 边权修 ...
- HDU 3966 Aragorn's Story 树链拋分
一.写在前面 终于开始开坑link-cut-tree这个了,对于网上找到的大佬的前进路线,进行了一番研发,发现实际上可以实现对于树链拋分的制作.经历了若干长时间之后终于打了出来(为什么每次学什么东西都 ...
随机推荐
- CSS Transform / Transition / Animation 属性的区别
back21 Jun 2011 Category: tech Tags: css 最近想UI的动画转到css3能吃进3d加速的属性上面来以加强动画的连贯性.只是对于css几个新加的属性不太熟悉,常常容 ...
- C#连接各种数据库的方法(文档)
1.C#连接连接Access程序代码: ------------------------------------------------------------------------------- ...
- springboot查找配置文件路径的过程
spring加载配置文件是通过listener监视器实现的,在springboot启动时: 在容器启动完成后会广播一个SpringApplicationEvent事件,而SpringApplicati ...
- checkbox 更新回显
if($row['name']==$_SESSION['name']){$checked="checked disabled";}else{$checked=" &quo ...
- 例举在诊断Oracle性能问题时,常用的工具、方法
例举在诊断Oracle性能问题时,常用的工具.方法 解答: 1)简单一点的可以用toad及dbartisan这样的工具. 2)纯做性能监测,比较出色的有spolight和emc的I3,这两个软件都比较 ...
- bootstrap随笔点击增加
ht5: <div class="form-group"><label class="col-sm-2 control-label&qu ...
- 读取csv格式的数据
1.直接上代码,关键是会用 2.代码如下: <?php #添加推荐到英文站 $file = fopen('code.csv','r'); while ($data = fgetcsv($file ...
- 直接下载jdk压缩包方式安装
分为下面5个步骤 1.官网下载JDK 2.检查是否安装jdk,解压缩,放到指定目录 3.配置环境变量 4.设置系统默认JDK 5. 测试jdk 1.官网下载JDK 地址: http://ww ...
- 两天学会DirectX 3D之第二天
提要 前几天非常easy地跑了一个DirectX 9 程序,以为DirectX就那么绘制,事实证明有点Naive了. 之前的那个程序最多也就是个固定流水线的东西. 可是今天要用DirectX11来写一 ...
- Response响应对象
1.HttpServletResponse HttpServletResponse是一个定义在Servlet API中的接口,继承自ServletReponse接口,用于封装HTTP响应消息.HTTP ...