hdu3966 Aragorn's Story 树链剖分
题目大意:
有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 树链剖分的更多相关文章
- HDU3669 Aragorn's Story 树链剖分 点权
HDU3669 Aragorn's Story 树链剖分 点权 传送门:http://acm.hdu.edu.cn/showproblem.php?pid=3966 题意: n个点的,m条边,每个点都 ...
- HDU 3966 Aragorn's Story 树链剖分+树状数组 或 树链剖分+线段树
HDU 3966 Aragorn's Story 先把树剖成链,然后用树状数组维护: 讲真,研究了好久,还是没明白 树状数组这样实现"区间更新+单点查询"的原理... 神奇... ...
- Aragorn's Story 树链剖分+线段树 && 树链剖分+树状数组
Aragorn's Story 来源:http://www.fjutacm.com/Problem.jsp?pid=2710来源:http://acm.hdu.edu.cn/showproblem.p ...
- HDU 3966 Aragorn's Story(树链剖分)(线段树区间修改)
Aragorn's Story Time Limit: 10000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- Hdu 3966 Aragorn's Story (树链剖分 + 线段树区间更新)
题目链接: Hdu 3966 Aragorn's Story 题目描述: 给出一个树,每个节点都有一个权值,有三种操作: 1:( I, i, j, x ) 从i到j的路径上经过的节点全部都加上x: 2 ...
- HDU 3966 Aragorn's Story 树链剖分+BIT区间修改/单点询问
Aragorn's Story Description Our protagonist is the handsome human prince Aragorn comes from The Lord ...
- hdu 3966 Aragorn's Story 树链剖分 按点
Aragorn's Story Time Limit: 10000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- HDU 3966 Aragorn's Story (树链剖分入门题)
树上路径区间更新,单点查询. 线段树和树状数组都可以用于本题的维护. 线段树: #include<cstdio> #include<iostream> #include< ...
- HDU 3966 Aragorn's Story 树链剖分
Link: http://acm.hdu.edu.cn/showproblem.php?pid=3966 这题注意要手动扩栈. 这题我交g++无限RE,即使手动扩栈了,但交C++就过了. #pragm ...
随机推荐
- ubuntu18.04 蓝牙打开无效,解决办法升级内核
http://kernel.ubuntu.com/~kernel-ppa/mainline/ 上面的链接是linux内核版本, 蓝牙不管用可能是linux内核版本过低,本人亲自实验过, 升级到4.20 ...
- sequelize 批量添加和更新数据 bulkCreate
sequelize提供了批量插入数据的方法:Model.bulkCreate([…object]). 例如: let updatePhone = [{userName: '李白‘},{userNam ...
- the install of mysql in Linux System
一.下载MySql 浏览器打开 https://www.mysql.com/downloads/mysql/#downloads 下载 我下载的版本是Red Hat 5 版本的 https://www ...
- Solidity字符串拼接实现oraclize动态查询
solidity本身没有字符串拼接功能,但是如果你恰巧要用oraclize api,那么可以使用oraclize api中的字符串拼接方法(strConcat).之所以oraclize api里会有s ...
- 性能优化之_android内存
优化内存使用主要是三个原则: CPU如何操纵特定的数据类型 数据和指令需要占用多少存储空间 数据在内存中的布局方式 处理大量数据时,使用可以满足要求的最小字节数据类型,能用short就不用int,能用 ...
- 数字图像处理实验(15):PROJECT 06-02,Pseudo-Color Image Processing 标签: 图像处理MATLAB 2017-05-27 20:53
实验要求: 上面的实验要求中Objective(实验目的)部分是错误的. 然而在我拿到的大纲中就是这么写的,所以请忽视那部分,其余部分是没有问题的. 本实验是使用伪彩色强调突出我们感兴趣的灰度范围,在 ...
- 498B Name That Tune
传送门 题目大意 n首音乐,第i首被听出来的概率为pi,刚开始听第一首,1s后如果听出来了则放第下一首,否则接着听这一首,第i首在连续听了ti s之后一定会被听出来,问Ts后听出来的歌的期望数量. 分 ...
- Luogu 4473 [国家集训队]飞飞侠
BZOJ 2143 新技能:并查集优化最短路. 暴力最短路是$O(n^4)$的,然后拿个线段树优化一下连边就$O($能过$)$了. 但是这样都太慢了. 我们考虑一个点如果之前被更新过了,那么之后就不会 ...
- jqentitydetail
using System;using System.Collections;using System.Collections.Generic;using System.Linq;using Syste ...
- Java静态变量的用法:伪单例
这几天遇到一个问题,一个Service里有一个map,但是这个Service有别的继承,于是每一个Service都会创建一个map,但是这个map应该是公用的,于是就有问题了...(按结构说Servi ...