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

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

线段树:

#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. HTML5课程

    1.新语义化标签:section.header.footer.nav.article.aside.figure.dialog.time.meter.mark.progress.video 2.最新的属 ...

  2. 移动端上下滑动事件之--坑爹的touch.js

    原文   http://blog.csdn.net/minidrupal/article/details/39611605 移动端页面的盛行,微信的便利的页面推广等等,让越来越多的css3效果和htm ...

  3. 嵌入式开发之davinci--- 8148/8168/8127 中的图像采集格式Sensor信号输出YUV、RGB、RAW DATA、JPEG 4种方式区别

    简单来说,YUV: luma (Y) + chroma (UV) 格式, 一般情况下sensor支持YUV422格式,即数据格式是按Y-U-Y-V次序输出的RGB: 传统的红绿蓝格式,比如RGB565 ...

  4. 再谈Unity调用Android的Activity

    这段时间在研究Unity4.3开发环境下.怎样调用由Android SDK4.4.2写的Activity.參考了非常多网上的博客.百度出了几十篇大部分都是转载雨松MOMO的,这里必须向雨松MOMO表示 ...

  5. ubuntu 用命令行设置chrome的proxy

    google-chrome-stable --proxy-server="IP proxy Server:port"

  6. DMSFrame 之查询表达式用法(一)

    where条件 WhereClip<Adm_User> where = new WhereClip<Adm_User>(q => q.DeleteFlag == fals ...

  7. 【转】msxml 操作xml

    转自http://blog.csdn.net/dai_jing/article/details/8393392,原始出处不详. 1.简介 在.NET平台,微软为C#或托管C++程序员提供了丰富的类库, ...

  8. 软件设计模式(Design pattern)(待续)

    软件设计模式是在面向对象的系统设计过程中反复出现的问题解决方案. 设计模式通常描述了一组相互紧密作用的类与对象. 设计模式提供一种讨论软件设计的公共语言,使得熟练设计者的设计经验可以被初学者和其他设计 ...

  9. [Go语言]从Docker源码学习Go——指针和Structs

    这两天在看reflect这个包在Docker中的使用时,遇到了各种问题,最后虽然知道怎么用了. 但是对于这块的原理还不是太懂,于是把"THE WAY TO GO"中关键的几章看了下 ...

  10. kafka 自启脚本

    每次使用的时候都要手动去启动真头痛! 解决办法,自启吧! 方法一: 方法一: /etc/rc.local中添加 文件地址记得替换掉 ,我没使用这种,发现不是每次都行,就换了第二种方法 /usr/loc ...