题目传送门

题目大意:

有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. ubuntu下不用eclipse开发cocos2d-x(命令行)

    之前在ubuntu下通过eclipse搭建开发cocos2d-x的环境,但是由于eclipse界面在ubuntu显得很丑,在里面写代码,完全没有感觉,后来我转到了win7上通过vs2010和eclip ...

  2. Docker学习之路(一)

    容器简介 管理程序虚拟化(hypervisor virtualization, HV)是通过中间虚拟运行于物理硬件之上.而容器是直接运行在操作系统内核之上用户空间.因此,容器虚拟化运行也成为“操作系统 ...

  3. Luogu 3241 [HNOI2015]开店

    BZOJ 4012权限题 浙科协的网突然炸了,好慌…… 据说正解是动态点分治,然而我并不会,我选择树链剖分 + 主席树维护. 设$dis_i$表示$i$到$root(1)$的值,那么对于一个询问$u$ ...

  4. bootstrap图片切换效果

    <!DOCTYPE html><html lang="zh-cn"><head><meta charset="utf-8&quo ...

  5. Requests接口测试(一)

    接口测试概念 接口测试是测试系统组件间接口的一种测试.接口测试主要用于检测外部系统与系统之间以及内部各个子系统之间的交互点.测试的重点是要检查数据的交换,传递和控制管理过程,以及系统间的相互逻辑依赖关 ...

  6. HTTP协议相关介绍

    一.HTTP请求方法 根据HTTP标准,HTTP请求可以使用多种请求方法.HTTP1.0定义了三种请求方法: GET, POST 和 HEAD方法.HTTP1.1新增了五种请求方法:OPTIONS, ...

  7. linux学习1----初涉linux

    linux因其稳定高效的特点,受到很多开发者的青睐,因此将其作为服务器的操作系统. 作为一名开发者,程序员,掌握了一定的linux知识和技巧,程序的开发部署和运行也有不小的帮助. linux由于其开源 ...

  8. HttpServletResponse函數

    一.負責向客戶端發送數據的方法 1.ServletOutStream getOutputStream() 获得一个Servlet字节流输出数据 案例: response.setHeader(" ...

  9. CentOS目录与文件操作

    pwd:查看当前目录 touch:创建文件 touch a.c ls:查看当前目录下文件,也可以ls /tmp查看tmp下的文件 rm:删除文件 rm a.c,也可以rm a.c -rf 强制删除 c ...

  10. 一套最全的JavaScript 语言基础知识点总结(思维导图10张)

    1.DOM基础操作 2.数组基础 3.函数基础 4.运算符 5.流程控制语句 6.正则表达式 7.字符串函数 8.数据类型 9.变量 10.window对象