URAL1553 Caves and Tunnels 树链剖分 动态树
URAL1553 维护一棵树,随时修改某个节点的权值,询问(x,y)路径上权值最大的点。
树是静态的,不过套动态树也能过,时限卡的严就得上树链剖分了。
还是那句话 splay的核心是splay(x) LCT的核心是access(x)
把SPOJ OTOCI的代码改了两行就过了
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm> using namespace std; const int MaxNode=131000; int Lch[MaxNode];
int Rch[MaxNode];
int Pnt[MaxNode];
int Data[MaxNode];
int Sum[MaxNode];
int Rev[MaxNode];
int List[MaxNode];
int maxv[MaxNode];
int Total; inline bool isRoot(int t){
return (!Pnt[t]||(Lch[Pnt[t]]!=t&&Rch[Pnt[t]]!=t));
}
inline void Update(int cur){
maxv[cur]=Data[cur];
if(Lch[cur]!=0)maxv[cur]=max(maxv[cur],maxv[Lch[cur]]);
if(Rch[cur]!=0)maxv[cur]=max(maxv[cur],maxv[Rch[cur]]);
}
void Reverse(int cur){
if (!Rev[cur]) return;
swap(Lch[cur],Rch[cur]);
Rev[Lch[cur]]^=1;
Rev[Rch[cur]]^=1;
Rev[cur]=0;
}
void LeftRotate(int cur){
if (isRoot(cur)) return;
int pnt=Pnt[cur],anc=Pnt[pnt];
Lch[pnt]=Rch[cur];
if (Rch[cur]) Pnt[Rch[cur]]=pnt;
Rch[cur]=pnt;
Pnt[pnt]=cur;
Pnt[cur]=anc;
if (anc){
if (Lch[anc]==pnt) Lch[anc]=cur;
else if (Rch[anc]==pnt) Rch[anc]=cur;
}
Update(pnt);
Update(cur);
}
void RightRotate(int cur){
if (isRoot(cur)) return;
int pnt=Pnt[cur],anc=Pnt[pnt];
Rch[pnt]=Lch[cur];
if (Lch[cur]) Pnt[Lch[cur]]=pnt;
Lch[cur]=pnt;
Pnt[pnt]=cur;
Pnt[cur]=anc;
if (anc){
if (Rch[anc]==pnt) Rch[anc]=cur;
else if (Lch[anc]==pnt) Lch[anc]=cur;
}
Update(pnt);
Update(cur);
}
void Splay(int cur){
int pnt,anc;
List[++Total]=cur;
for (int i=cur;!isRoot(i);i=Pnt[i]) List[++Total]=Pnt[i];
for (;Total;--Total)
if (Rev[List[Total]]) Reverse(List[Total]);
while (!isRoot(cur)){
pnt=Pnt[cur];
if (isRoot(pnt)){// 父亲是根结点,做一次旋转
if (Lch[pnt]==cur) LeftRotate(cur);
else RightRotate(cur);
}
else{
anc=Pnt[pnt];
if (Lch[anc]==pnt){
if (Lch[pnt]==cur) LeftRotate(pnt),LeftRotate(cur);// 一条线
else RightRotate(cur),LeftRotate(cur);// 相反两次
}
else{
if (Rch[pnt]==cur) RightRotate(pnt),RightRotate(cur);// 一条线
else LeftRotate(cur),RightRotate(cur);// 相反两次
}
}
}
}
int Expose(int u){
int v=0;
for (;u;u=Pnt[u]) Splay(u),Rch[u]=v,v=u,Update(u);
for (;Lch[v];v=Lch[v]);
return v;
}
void Modify(int x,int d){
Splay(x);
Data[x]=d;
Update(x);
}
int Query(int x,int y){
int rx=Expose(x),ry=Expose(y);
if (rx==ry){
for (int u=x,v=0;u;u=Pnt[u]){
Splay(u);
if (!Pnt[u]) return max(max(maxv[Rch[u]],Data[u]),maxv[v]);
Rch[u]=v;
Update(u);
v=u;
}
}
return -1;
}
bool Join(int x,int y){
int rx=Expose(x),ry=Expose(y);
if (rx==ry) return false;
else{
Splay(x);
Rch[x]=0;
Rev[x]=1;
Pnt[x]=y;
Update(x);
return true;
}
}
void Cut(int x){
if (Pnt[x]){
Expose(x);
Pnt[Lch[x]]=0;
Lch[x]=0;
Update(x);
}
}
int n,Q; void init(){
Total=0;
memset(Rev,0,sizeof(Rev));
memset(Pnt,0,sizeof(Pnt));
memset(Lch,0,sizeof(Lch));
memset(Rch,0,sizeof(Rch));
memset(Sum,0,sizeof(Sum));
memset(Data,0,sizeof(Data));
memset(maxv,0,sizeof(maxv));
}
char cmd[22];
int main()
{ freopen("t.txt","r",stdin);
init();
scanf("%d",&n);
for(int i=0;i<n-1;i++)
{
int a,b;
scanf("%d%d",&a,&b);
Join(a,b);
}
scanf("%d",&Q);
while (Q--){
int x,y;
scanf("%s%d%d",cmd,&x,&y);
if (cmd[0]=='I'){
Modify(x,Data[x]+y);
}
if (cmd[0]=='G'){
printf("%d",Query(x,y));
if(Q>0)printf("\n");
} }
return 0;
}
URAL1553 Caves and Tunnels 树链剖分 动态树的更多相关文章
- luogu3703 [SDOI2017]树点涂色(线段树+树链剖分+动态树)
link 你谷的第一篇题解没用写LCT,然后没观察懂,但是自己YY了一种不用LCT的做法 我们考虑对于每个点,维护一个fa,代表以1为根时候这个点的父亲 再维护一个bel,由于一个颜色相同的段一定是一 ...
- 【bzoj5210】最大连通子块和 树链剖分+线段树+可删除堆维护树形动态dp
题目描述 给出一棵n个点.以1为根的有根树,点有点权.要求支持如下两种操作: M x y:将点x的点权改为y: Q x:求以x为根的子树的最大连通子块和. 其中,一棵子树的最大连通子块和指的是:该子树 ...
- 【bzoj4712】洪水 树链剖分+线段树维护树形动态dp
题目描述 给出一棵树,点有点权.多次增加某个点的点权,并在某一棵子树中询问:选出若干个节点,使得每个叶子节点到根节点的路径上至少有一个节点被选择,求选出的点的点权和的最小值. 输入 输入文件第一行包含 ...
- 【bzoj4999】This Problem Is Too Simple! 树链剖分+动态开点线段树
题目描述 给您一颗树,每个节点有个初始值. 现在支持以下两种操作: 1. C i x(0<=x<2^31) 表示将i节点的值改为x. 2. Q i j x(0<=x<2^31) ...
- P3313 [SDOI2014]旅行——树链剖分+线段树(动态开点?)
P3313 [SDOI2014]旅行 一棵树,其中的点分类,点有权值,在一条链上找到一类点中的最大值或总和: 树链剖分把树变成链: 把每个宗教单开一个线段树,维护区间总和和最大值: 宗教很多,需要动态 ...
- 洛谷P3313 [SDOI2014]旅行 题解 树链剖分+线段树动态开点
题目链接:https://www.luogu.org/problem/P3313 这道题目就是树链剖分+线段树动态开点. 然后做这道题目之前我们先来看一道不考虑树链剖分之后完全相同的线段树动态开点的题 ...
- BZOJ 3589 动态树 (树链剖分+线段树)
前言 众所周知,90%90\%90%的题目与解法毫无关系. 题意 有一棵有根树,两种操作.一种是子树内每一个点的权值加上一个同一个数,另一种是查询多条路径的并的点权之和. 分析 很容易看出是树链剖分+ ...
- B20J_3231_[SDOI2014]旅行_树链剖分+线段树
B20J_3231_[SDOI2014]旅行_树链剖分+线段树 题意: S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,城市信仰不同的宗教,为了方便,我们用不同的正整数代表各种宗教. S国 ...
- 【BZOJ-2325】道馆之战 树链剖分 + 线段树
2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 1153 Solved: 421[Submit][Statu ...
随机推荐
- assert.ok()详解
assert.ok(value[, message]) 测试 value 是否为真值.它等同于 assert.equal(!!value, true, message). 如果 value 不是真值, ...
- django-3 admin开启后台配置并展示表内容
设置了superuser 之后,可以在run server 后, 通过浏览器访问后台,进行界面配置. 1. python manage.py creatersuperuser 此命令在manage.p ...
- Python面向对象之类属性类方法静态方法
类的结构 实例 使用面向对象开发时,第一步是设计类: 当使用 类名() 创建对象时,会自动执行以下操作: 1.为对象在内存中分配空间--创建对象: 2.为对象的属性 设置初始值--初始化方法(init ...
- 分数拆分(刘汝佳紫书P183)
枚举,由已知条件推得y大于k,小于等于2K AC代码: #include"iostream"#include"cstring"using namespace s ...
- 细说php第八章笔记(初稿)
8.1 函数的定义 函数是被命名的: 函数是独立的: 函数执行特定的任务: 函数可以用将一个返回值返回给调用他的程序 函数的优越性 提高程序的重用性 ...
- Webdriver测试脚本2(控制浏览器)
Webdriver提供了操作浏览器的一些方法,例如控制浏览器的大小.操作浏览器前进和后退等. 控制浏览器窗口大小 有时候我们希望能以某种浏览器尺寸打开,让访问的页面在这种尺寸下运行.例如可以将浏览器设 ...
- POJ-2594 Treasure Exploration floyd传递闭包+最小路径覆盖,nice!
Treasure Exploration Time Limit: 6000MS Memory Limit: 65536K Total Submissions: 8130 Accepted: 3 ...
- Codeforces713D. Animals and Puzzle
$n<=1000,m<=1000$,$n*m$的01矩阵,给$t<=1000000$个询问,每次问一个矩形中最大的1正方形的边长. 先想想不考虑“一个矩形中”的限制,那记$f(i,j ...
- hosts.allow和hosts.deny文件
之前想通过外部主机访问自己主机上的VMWare虚拟机,使用了VMWare的NAT端口映射,经过一番尝试,算是成功了,总结一下. VMWare NAT端口映射就可以将虚拟机上的服务映射成自己主机上的端口 ...
- SOJ 3531_Number Pyramids
[题意]给定一个数top及最底层元素个数n,构成一个以给top为塔尖,层数为n的如杨辉三角的金字塔,求有多少种 [分析]最终种数其实只与最底层的n个数的组合数有关,上层的每个都数是由最底层数相加得来 ...