题目传送门

题目大意:

有n个兵营形成一棵树,给出q次操作,每一次操作可以使两个兵营之间的所有兵营的人数增加或者减少同一个数目,每次查询输出某一个兵营的人数。

思路:

树链剖分模板题,讲一下树链剖分过程的理解。

第一步,dfs,记录每个节点的父节点,子节点数目,重子节点,树的深度。

第二步,dfs,处理出dfs序和轻重链的起点,重链形成一条,轻链的起点就是本身,处理dfs序的时候先处理重链的dfs序。

修改,利用树状数组(或者线段树),个人认为这是最难的地方。

inline void change(int u,int v,int d)
{
int f1=top[u],f2=top[v];
while(f1!=f2)
{
if(deep[f1]<deep[f2])
{
swap(f1,f2),swap(u,v);
}
upp(p[f1],d);
upp(p[u]+1,-d);//每次更新一条链
u=fa[f1]; //处理完后必须往父节点走,否则死循环
f1=top[u];
}
if(deep[u]>deep[v])swap(u,v);//最后处在同一条重链上时,重链的上半部分是不需要更新的
upp(p[u],d);
upp(p[v]+1,-d); }

  查询,树状数组,由于每次修改的时候都是通过change来实现的而不是up来实现的,所以树状数组getsum得到的就是某一个点的值而不是前缀和。

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<vector>
#include<map>
#include<set>
#include<cstring>
#include<queue>
#include<stack>
#include<stdlib.h>
#include<unordered_map>
#define CLR(a,b) memset(a,b,sizeof(a))
#define mkp(a,b) make_pair(a,b)
typedef long long ll;
using namespace std;
const int maxn=;
int n,m,q,tot,head[maxn],rs[maxn],A[maxn],pos=;
struct edge{
int to,Next;
}a[maxn*];
inline void init(){
tot=;
CLR(rs,);
CLR(head,-);
pos=;
}
inline void addv(int u,int v){
a[++tot]={v,head[u]};
head[u]=tot;
}
inline int lowbit(int x){return x&(-x);}
inline void upp(int x,int val)
{
while(x<=n)
{
rs[x]+=val;
x+=lowbit(x);
}
}
inline getsum(int x)
{
int ans=;
while(x)
{
ans+=rs[x];
x-=lowbit(x);
}
return ans;
}
int size[maxn],deep[maxn];
int fa[maxn],son[maxn],top[maxn];
int p[maxn],fp[maxn];
inline void dfs_1(int u,int f,int d)
{
fa[u]=f;
deep[u]=d;
size[u]=;
son[u]=-;
for(int i = head[u] ; i != -;i = a[i].Next)
{
int v=a[i].to;
if(v != f)
{
dfs_1(v,u,d+);
size[u]+=size[v];
if(son[u]==-||size[son[u]]<size[v])
{
son[u]=v;
}
}
}
}
inline void dfs_2(int u,int st)
{
top[u]=st;
p[u]=pos++;
fp[pos]=u;
if(son[u] == -) return;
dfs_2(son[u],st);
for(int i=head[u];i!=-;i=a[i].Next)
{
int v=a[i].to;
if(fa[u]!=v&&son[u]!=v)
dfs_2(v,v);
}
}
inline void change(int u,int v,int d)
{
int f1=top[u],f2=top[v];
while(f1!=f2)
{
if(deep[f1]<deep[f2])
{
swap(f1,f2),swap(u,v);
}
upp(p[f1],d);
upp(p[u]+,-d);//每次更新一条链
u=fa[f1];//往父节点走
f1=top[u];
}
if(deep[u]>deep[v])swap(u,v);
upp(p[u],d);
upp(p[v]+,-d); }
int main(){
while(scanf("%d%d%d",&n,&m,&q)!=EOF)
{
init();
for(int i=;i<=n;i++)
{
scanf("%d",&A[i]);
}
for(int i=;i<n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
addv(u,v);
addv(v,u);
}
dfs_1(,-,);
dfs_2(,);
for(int i=;i<=n;i++)
{
change(i,i,A[i]);
}
for(int i=;i<q;i++)
{
char c;
int u,v;
scanf(" %c",&c);
if( c == 'Q' )
{
scanf("%d",&u);
printf("%d\n",getsum(p[u]));
}else{
int d;
scanf("%d%d%d",&u,&v,&d);
if( c == 'D' ) d*=-;
change(u,v,d);
}
}
}
}

hdu3966 Aragorn's Story 树链剖分的更多相关文章

  1. HDU3669 Aragorn's Story 树链剖分 点权

    HDU3669 Aragorn's Story 树链剖分 点权 传送门:http://acm.hdu.edu.cn/showproblem.php?pid=3966 题意: n个点的,m条边,每个点都 ...

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

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

  3. Aragorn's Story 树链剖分+线段树 && 树链剖分+树状数组

    Aragorn's Story 来源:http://www.fjutacm.com/Problem.jsp?pid=2710来源:http://acm.hdu.edu.cn/showproblem.p ...

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

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

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

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

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

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

  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 (树链剖分入门题)

    树上路径区间更新,单点查询. 线段树和树状数组都可以用于本题的维护. 线段树: #include<cstdio> #include<iostream> #include< ...

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

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

随机推荐

  1. 堡垒机(paramiko)

    实现思路 堡垒机执行流程: 管理员为用户在服务器上创建账号(将公钥放置服务器,或者使用用户名密码) 用户登陆堡垒机,输入堡垒机用户名密码,现实当前用户管理的服务器列表 用户选择服务器,并自动登陆 执行 ...

  2. EZOJ #201

    传送门 分析 这个题和寿司晚宴有点像 我们知道大于$\sqrt n$的质因子最高就是一次 于是我们对所有数以他的大质数为关键字排序 设dp[i][p2][p3][p5][p7][p11][p13][0 ...

  3. Vim编码知识,乱码问题

    原文:http://demi-panda.com/2012/12/26/vim-encoding/ 在vim的初始学习阶段,乱码经常是困扰新手的一个比较烦躁的问题,本文试图阐述Vim的编码知识,及设置 ...

  4. properties配置文件在idea中默认utf-8编码可能会乱码的解决

    使用idea集成开发环境时,有时在properties配置文件有中文,在线上拿到的时乱码,如何解决? 这样设置: 最后说一下,setting设置是对当前项目的,想要所有的项目都有相同的设置,需要在 中 ...

  5. 跨域Ajax请求(jQuery JSONP MVC)

    通过jQuery的$.ajax方法发送JSONP请求 js代码 <script type="text/javascript"> function jsonptest2( ...

  6. 再次迷宫救人——BFS

    原创 上次用DFS解了迷宫救人:https://www.cnblogs.com/chiweiming/p/9313164.html 这次用BFS(广度优先搜索),实现广度优先搜索比深度优先搜索复杂,思 ...

  7. python中的os模块几个常用的方法

    os.getcwd() 得到当前工作目录,即当前python脚本工作的目录路径 os.remove(file):删除一个文件 os.mkdir(name):创建目录 os.path.exists(na ...

  8. Android Canvas的save(),saveLayer()和restore()浅谈

    save()  saveLayer()  restore() 1.在自定义控件当中你onMeasure和onLayout的工作做完成以后就该绘制该控件了,有时候需要自己在控件上添加一些修饰来满足需求 ...

  9. Ubuntu16.04修改静态ip地址

    https://blog.csdn.net/mdw5521/article/details/79270035

  10. WPF的Image控件图片不能显示出来的问题探究

    在wpf项目中,用Image来显示资源图片,在界面是可以显示,但是在运行的时候却显示不出来. <Image Source=" HorizontalAlignment="Lef ...