树上路径区间更新,单点查询。

线段树和树状数组都可以用于本题的维护。

线段树:

#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 (树链剖分入门题)的更多相关文章

  1. HDU 3966 Aragorn's Story(树链剖分)(线段树区间修改)

    Aragorn's Story Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  2. HDU 3966 Aragorn's Story 树链剖分+树状数组 或 树链剖分+线段树

    HDU 3966 Aragorn's Story 先把树剖成链,然后用树状数组维护: 讲真,研究了好久,还是没明白 树状数组这样实现"区间更新+单点查询"的原理... 神奇... ...

  3. Hdu 3966 Aragorn's Story (树链剖分 + 线段树区间更新)

    题目链接: Hdu 3966 Aragorn's Story 题目描述: 给出一个树,每个节点都有一个权值,有三种操作: 1:( I, i, j, x ) 从i到j的路径上经过的节点全部都加上x: 2 ...

  4. HDU 3966 Aragorn's Story 树链剖分+BIT区间修改/单点询问

    Aragorn's Story Description Our protagonist is the handsome human prince Aragorn comes from The Lord ...

  5. HDU 3966 Aragorn's Story 树链剖分

    Link: http://acm.hdu.edu.cn/showproblem.php?pid=3966 这题注意要手动扩栈. 这题我交g++无限RE,即使手动扩栈了,但交C++就过了. #pragm ...

  6. hdu 3966 Aragorn's Story : 树链剖分 O(nlogn)建树 O((logn)²)修改与查询

    /** problem: http://acm.hdu.edu.cn/showproblem.php?pid=3966 裸板 **/ #include<stdio.h> #include& ...

  7. hdu 3966 Aragorn's Story 树链剖分 按点

    Aragorn's Story Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  8. HDU 3966 Aragorn's Story (树链点权剖分,成段修改单点查询)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3966 树链剖分的模版,成段更新单点查询.熟悉线段树的成段更新的话就小case啦. //树链剖分 边权修 ...

  9. HDU 3966 Aragorn's Story 树链拋分

    一.写在前面 终于开始开坑link-cut-tree这个了,对于网上找到的大佬的前进路线,进行了一番研发,发现实际上可以实现对于树链拋分的制作.经历了若干长时间之后终于打了出来(为什么每次学什么东西都 ...

随机推荐

  1. 对PHP输入输出流学习和认识

    PHP输入和输出流是通过php://来访问的,它允许访问 PHP 的输入输出流.标准输入输出和错误描述符, 内存中.磁盘备份的临时文件流以及可以操作其他读取写入文件资源的过滤器. php://stdi ...

  2. ASP.NET中26种性能优化方法

    系统类  Type类,Object类,String类, Arrary类,Console类, Exception类,GC类, MarshalByRefObject类, Math类. DateTime结构 ...

  3. Docker:通过Git部署

    这是我翻译的国外博客,如需转载请注明出处和原文链接 我一直听说Docker是个很棒的新事物,但是我一直提不起兴趣,直到我遇到一个切实的问题: 如果通过Docker来部署 Scout ,这么做会轻松一些 ...

  4. c++新特性---引用变量

    一.定义 引用变量是已定义变量的别名,如将ra设置为a的引用变量,则可以使用ra和a交替使用该变量. 表示: int a = 5; int & ra = a; 其中&不是地址运算符,而 ...

  5. JDB调试之小试牛刀

    用JDK自带工具JDB调试示例程序HelloJDB(d:\jdb\HelloJDB) HelloJDB代码如下: public class HelloJDB { public static void ...

  6. JavaScript------日期和时间戳的相互转换

    var date = new Date(); 日期转时间戳 Number(date)或者date.getTime(); //只是转换成了纯数字的时间戳,例如:1498144203861需要转换才能使用 ...

  7. thrift框架总结,可伸缩的跨语言服务开发框架

    thrift框架总结,可伸缩的跨语言服务开发框架 前言: 目前流行的服务调用方式有很多种,例如基于 SOAP 消息格式的 Web Service,基于 JSON 消息格式的 RESTful 服务等.其 ...

  8. tfs+git

    TFS+GIT 一:背景介绍 技术团队的代码管理工具原来使用的是纯TFS方案,使用两年后发现一些问题:体积太大,每次新建一个分支需要本地下载一份代码:操作不便,功能分支的建立.合并不方便,本地有很多同 ...

  9. 【BZOJ2208】[Jsoi2010]连通数 DFS

    [BZOJ2208][Jsoi2010]连通数 Description Input 输入数据第一行是图顶点的数量,一个正整数N. 接下来N行,每行N个字符.第i行第j列的1表示顶点i到j有边,0则表示 ...

  10. cdr X6 64位32位缩略图补丁包

    cdr X6 64位32位缩略图补丁包下载 安装了X6没有缩略图的话,点击下面链接下载安装插件即可 点击下载