hdu3966_树链剖分
近期在强化知识点深度。发现树链剖分不是非常会写了。
回想一下改动操作:
若两个点在同一条链上,则直接改动这段区间。
若不在同一条链上,改动深度较大的点到其链顶端的区间,同一时候将这个点变为他所在链顶端的父亲,循环操作直到这两个点在同一条链上。就能够用上一种方法了。
没实用LCA写是由于曾经被坑过,不但没有这样的方法好写。效率也不太让人惬意。
主要是对另外一种情况怎样写有所遗忘。写道模版再给自己提个醒。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
#define MAXN 50005
int n,m,q;
vector<int> map[MAXN];
int size[MAXN],fa[MAXN],son[MAXN],val[MAXN],tid[MAXN],_tid[MAXN],dep[MAXN],top[MAXN];
int cnt;
struct node
{
int l,r,val;
}tree[MAXN<<2];
void dfs1(int s,int f,int d)
{
size[s]=1;
fa[s]=f;
dep[s]=d;
int len=map[s].size();
for(int i=0;i<len;i++)
{
int e=map[s][i];
if(e==f)continue;
dfs1(e,s,d+1);
size[s]+=size[e];
if(son[s]==0)
son[s]=e;
else if(size[son[s]]<size[e])
son[s]=e;
}
}
void dfs2(int s,int t)
{
tid[s]=++cnt;
_tid[cnt]=s;
top[s]=t;
if(son[s]!=0)
dfs2(son[s],t);
int len=map[s].size();
for(int i=0;i<len;i++)
{
int e=map[s][i];
if(e!=fa[s] && e!=son[s])
dfs2(e,e);
}
}
void build(int l,int r,int now)
{
tree[now].l=l;
tree[now].r=r;
tree[now].val=0;
if(l==r)
{
tree[now].val=val[_tid[l]];
return ;
}
int mid=(l+r)>>1;
build(l,mid,now<<1);
build(mid+1,r,now<<1|1);
}
void down(int now)
{
tree[now<<1].val+=tree[now].val;
tree[now<<1|1].val+=tree[now].val;
tree[now].val=0;
}
void update(int l,int r,int now,int num)
{
if(l==tree[now].l && r==tree[now].r)
{
tree[now].val+=num;
return ;
}
if(tree[now].val)
down(now);
int mid=(tree[now].l+tree[now].r)>>1;
if(r<=mid)
update(l,r,now<<1,num);
else if(l>mid)
update(l,r,now<<1|1,num);
else
{
update(l,mid,now<<1,num);
update(mid+1,r,now<<1|1,num);
}
}
void change(int s,int e,int num)
{
while(top[s]!=top[e])
{
if(dep[top[s]]<dep[top[e]])
swap(s,e);
update(tid[top[s]],tid[s],1,num);
s=fa[top[s]];
}
if(dep[s]>dep[e])
swap(s,e);
update(tid[s],tid[e],1,num);
}
int query(int l,int now)
{
if(tree[now].l==l && tree[now].r==l)
return tree[now].val;
if(tree[now].val)
down(now);
int mid=(tree[now].l+tree[now].r)>>1;
if(l<=mid)
return query(l,now<<1);
else
return query(l,now<<1|1);
}
int main()
{
while(cin>>n>>m>>q)
{
memset(size,0,sizeof(size));
memset(fa,0,sizeof(fa));
memset(tid,0,sizeof(tid));
memset(son,0,sizeof(son));
cnt=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&val[i]);
map[i].clear();
}
for(int i=1;i<n;i++)
{
int a,b;
scanf("%d%d",&a,&b);
map[a].push_back(b);
map[b].push_back(a);
}
dfs1(1,-1,1);
dfs2(1,1);
build(1,n,1);
while(q--)
{
char ch[5];
int a,b,c;
scanf("%s",ch);
if(ch[0]=='Q')
{
scanf("%d",&a);
printf("%d\n",query(tid[a],1));
}
else
{
scanf("%d%d%d",&a,&b,&c);
if(ch[0]=='I')
change(a,b,c);
else
change(a,b,-c);
}
}
}
}
hdu3966_树链剖分的更多相关文章
- BZOJ 3626: [LNOI2014]LCA [树链剖分 离线|主席树]
3626: [LNOI2014]LCA Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2050 Solved: 817[Submit][Status ...
- BZOJ 1984: 月下“毛景树” [树链剖分 边权]
1984: 月下“毛景树” Time Limit: 20 Sec Memory Limit: 64 MBSubmit: 1728 Solved: 531[Submit][Status][Discu ...
- codevs 1228 苹果树 树链剖分讲解
题目:codevs 1228 苹果树 链接:http://codevs.cn/problem/1228/ 看了这么多树链剖分的解释,几个小时后总算把树链剖分弄懂了. 树链剖分的功能:快速修改,查询树上 ...
- 并查集+树链剖分+线段树 HDOJ 5458 Stability(稳定性)
题目链接 题意: 有n个点m条边的无向图,有环还有重边,a到b的稳定性的定义是有多少条边,单独删去会使a和b不连通.有两种操作: 1. 删去a到b的一条边 2. 询问a到b的稳定性 思路: 首先删边考 ...
- 树链剖分+线段树 CF 593D Happy Tree Party(快乐树聚会)
题目链接 题意: 有n个点的一棵树,两种操作: 1. a到b的路径上,给一个y,对于路径上每一条边,进行操作,问最后的y: 2. 修改某个条边p的值为c 思路: 链上操作的问题,想树链剖分和LCT,对 ...
- 树链剖分+线段树 HDOJ 4897 Little Devil I(小恶魔)
题目链接 题意: 给定一棵树,每条边有黑白两种颜色,初始都是白色,现在有三种操作: 1 u v:u到v路径(最短)上的边都取成相反的颜色 2 u v:u到v路径上相邻的边都取成相反的颜色(相邻即仅有一 ...
- bzoj2243树链剖分+染色段数
终于做了一道不是一眼出思路的代码题(⊙o⊙) 之前没有接触过这种关于染色段数的题目(其实上课好像讲过),于是百度了一下(现在思维能力好弱) 实际上每一段有用的信息就是总共有几段和两段各是什么颜色,在开 ...
- bzoj3631树链剖分
虽然是水题1A的感觉太爽了O(∩_∩)O~ 题意相当于n-1次树上路径上每个点权值+1,最后问每个点的权值 本来想写线段树,写好了change打算框架打完了再来补,结果打完发现只是区间加和单点查 前缀 ...
- BZOJ 3531: [Sdoi2014]旅行 [树链剖分]
3531: [Sdoi2014]旅行 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1685 Solved: 751[Submit][Status] ...
随机推荐
- 【转】iOS程序自动检测更新的实现 -- 思路不错
原文网址:http://blog.csdn.net/davidsph/article/details/8931718 之前项目需要用到app自动更新的功能,现将实现方案分享出来.iOS程序自动提示更新 ...
- 常见Java集合的实现细节
1. Set和Map Set代表一种集合元素无序.集合元素不可重复的集合,Map则代表一种由多个key-value对组成的集合,Map集合类似于传统的关联数组.表面上看它们之间相似性很少,但实际上Ma ...
- php模版静态化原理
看了一些开源系统的,简单的总结一下php的模板及静态原理. 先贴代码,再做解释. index.php <?php //如果已存在静态页面,直接读取并显示 if(file_exists('inde ...
- spring-boot结合mybatis-spring的一个例子
首先spring-boot是用于简化配置的,具有可拔式组件的运用特点. 然后一下是spring-boot结合mybatis-spring的一个例子. 是一个maven项目 demo下载:http:// ...
- P1304 哥德巴赫猜想
题目描述 输入N(N<=10000),验证4~N所有偶数是否符合哥德巴赫猜想. (N为偶数). 如果一个数,例如10,则输出第一个加数相比其他解法最小的方案.如10=3+7=5+5,则10=5+ ...
- 获取json的节点名称
好几次想取json的节点名称,今天搞定了. procedure GetJsonNames(o: ISuperObject; Strs: TStrings); var ite: TSuperAvlIte ...
- bootstrap3的 progress 进度条
: 2.3版 3.0版 .bar .progress-bar .bar-* .progress-bar-* 2.代码: <!DOCTYPE html PUBLIC & ...
- layui table 时间戳
, { field: , title: '时间', templet: '<div>{{ laytpl.toDateString(d) }}</div>' }, 或者 , { f ...
- linux中errno使用(转)
当linux中的C api函数发生异常时,一般会将errno变量(需include errno.h)赋一个整数值,不同的值表示不同的含义,可以通过查看该值推测出错的原因,在实际编程中用这一招解决了不少 ...
- java equals的用法
equals方法,用于比较两个对象是否相同,它其实就是使用两个对象的内存地址在比较.Object类中的equals方法内部使用的就是==比较运算符. package Xuexi; public cla ...