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 ...
随机推荐
- linux 命令终端提示符显示-bash-4.2#解决方法
原地址:http://blog.csdn.net/liulihui1988/article/details/52796395 终端提示符显示的是-bash-4.2# 而不是root@主机名 + 路径的 ...
- private关键字
Student.java /* * 学生类 * * 通过对象直接访问成员变量,会存在数据安全问题 * 这个时候,我们就想能不能不让外界对象直接访问成员变量呢? * 答案:能 * 如何实现呢? * pr ...
- JavaEE JDBC PreparedStatement
PreparedStatement @author ixenos PreparedStatement工作原理 注意:虽然mysql不支持PreparedStatement优化,但依然有预编译的实现! ...
- [luoguP1011] 车站(递推)
传送门 蒟蒻我关系式没有找出来. 直接模拟递推过程好了. 代码 #include <cstdio> #define N 21 int a, n, m, x, y; int up[N][2] ...
- [luoguP1045] 麦森数(快速幂 + 高精度)
传送门 这道题纯粹是考数学.编程复杂度不大(别看我写了一百多行其实有些是可以不必写的). 计算位数不必用高精时刻存,不然可想而知时间复杂度之大.首先大家要知道一个数学公式 logn(a*b)=logn ...
- [NOIP2008] 提高组 洛谷P1125 笨小猴
题目描述 笨小猴的词汇量很小,所以每次做英语选择题的时候都很头疼.但是他找到了一种方法,经试验证明,用这种方法去选择选项的时候选对的几率非常大! 这种方法的具体描述如下:假设maxn是单词中出现次数最 ...
- CF601D:Acyclic Organic Compounds
给n<=300000的树,每个点上有一个字母,一个点的权值为:从该点出发向下走到任意节点停下形成的不同字符串的数量,问最大权值. 题目本身还有一些奇怪要求在此忽略.. Trie合并的模板题. # ...
- 【http_load】http_load性能测试工具使用详解
1.什么是http_loadhttp_load是一款基于Linux平台的web服务器性能测试工具,用于测试web服务器的吞吐量与负载,web页面的性能. 2.http_load的安装1)下载地址wge ...
- POJ2632 Crashing Robots 解题报告
Description In a modernized warehouse, robots are used to fetch the goods. Careful planning is neede ...
- CentOS firewall添加开放端口
添加 firewall-cmd --zone=public --add-port=80/tcp --permanent (–permanent永久生效,没有此参数重启后失效) 重新载入 firewal ...