题目传送门

题目大意:

有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. 项目代码:js

    1 //获取发文时间 function selectWriteTime(){ $("#writing_time_index").on("click"," ...

  2. 当集合里存储的是URL时的一些问题总结

    先看道题吧: package com.lk.C; import java.net.MalformedURLException; import java.net.URL; import java.uti ...

  3. python-memcached模块

    memcache memcache介绍 memcache概念 Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库 ...

  4. CF547D Mike and Fish

    欧拉回路,巧妙的解法. 发现每一个点$(x, y)$实际上是把横坐标和$x$和纵坐标$y$连一条线,然后代进去跑欧拉回路,这样里一条边对应了一个点,我们只要按照欧拉回路间隔染色即可. 注意到原图可能并 ...

  5. Part10-C语言环境初始化-一跃进入C大门lesson3

    1.跳转到c代码 因为内存中的代码来自于垫脚石SRAM,他们是相同的. 采用绝对跳转方式来完成. 因为我们是从汇编代码跳转到c语言的程序,所以我们要提前准备一个main.c文件. 修改makefile ...

  6. javascript总结18:javascript DOM简介

    1 HTML DOM 使 JavaScript 有能力对 HTML 事件做出反应.在事件发生时,执行JavaScript 方法,做出交互. 2 格式: onclick=JavaScript脚本 3 H ...

  7. 换零钞——第九届蓝桥杯C语言B组(国赛)第一题

    原创 标题:换零钞 x星球的钞票的面额只有:100元,5元,2元,1元,共4种.小明去x星旅游,他手里只有2张100元的x星币,太不方便,恰好路过x星银行就去换零钱.小明有点强迫症,他坚持要求200元 ...

  8. wp7启动+幻灯片效果

    using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Wi ...

  9. Jenkins 自动化部署asp.net

    使用步骤 1.安装jenkins.git和vs,并确保机器上安装了.net framework 4.5和.net framework4.0 ,完成后访问http://localhost:8080. 2 ...

  10. Kotlin if else判断

    Kotlin的if相对与java,有着较为灵活的用法. if是用来判断. if在Kotlin里面可以作为表达式来使用. 如果熟悉C java C#等 A>B:A?B这个判断应该是很熟悉,而Kot ...