hdu 2475 BOX (splay)
版权声明:本文为博主原创文章,未经博主允许不得转载。
Splay树是一种神奇的东西。。。
题意:
有一些箱子,要么放在地上,要么放在某个箱子里面 。
现在有两种操作:
(1) MOVE x y: 把 x 号箱子放到 y 号箱子里面,操作不合法就忽略这一次操作 。
(2) QUERY x : 查询 x 号箱子最外面的箱子是哪一个
解法:
首先对所有的树进行一遍DFS,得到一个DFS序,可以把它看成是一个括号序列,开始访问某个节点是左括号,结束访问时是右括号 。这样这题就转换成用Splay树来维护这个序列 。
对于MOVE操作:
将 x 对应那一段序列切下来,并将其放到 y 对应左括号的右边 。
对于QUERY操作:
直接查询以 x 为根的子树的最小值 。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <queue>
#include <set>
#include <vector>
#include <map>
#define ll long long using namespace std; const int N=; // 前向星
struct edge{
int to,nex;
}e[N];
int cnt;
int head[N]; inline void addedge(int u,int v){
e[cnt].to=v;
e[cnt].nex=head[u];
head[u]=cnt++;
} int id[N*]; // DFS序
int cou; int tot;
struct tree{
int key,fa,son[];
}t[N*];
int L[N],R[N]; // 第i个箱子所对应的左右括号在Splay树上的序号 inline void pushup(int x){}
inline void pushdown(int x){} inline void rotate(int x,int p){
int y=t[x].fa;
pushdown(y);
pushdown(x); t[y].son[!p]=t[x].son[p];
t[t[x].son[p]].fa=y;
t[x].fa=t[y].fa;
if (t[x].fa)
t[t[x].fa].son[t[t[x].fa].son[]==y]=x;
t[x].son[p]=y;
t[y].fa=x;
pushup(y);
pushup(x);
} inline void Splay(int x,int to){
while (t[x].fa!=to){
if (t[t[x].fa].fa==to)
rotate(x,t[t[x].fa].son[]==x);
else {
int y=t[x].fa, z=t[y].fa;
int p=(t[z].son[]==y);
if (t[y].son[p]==x)
rotate(x,!p),rotate(x,p);
else
rotate(y,p),rotate(x,p);
}
}
} inline int newnode(int key,int fa){
int x=tot++;
t[x].key=key;
t[x].fa=fa;
t[x].son[]=t[x].son[]=; if (key>) L[key]=x;
else R[-key]=x; return x;
} inline int get_min(int x){
while (t[x].son[]!=)
x=t[x].son[];
return x;
} inline int get_max(int x){
while (t[x].son[]!=)
x=t[x].son[];
return x;
} inline int bulid(int l,int r,int fa){
if (l>r) return ;
int x,mid=(l+r)>>;
x=newnode(id[mid],fa);
t[x].son[]=bulid(l,mid-,x);
t[x].son[]=bulid(mid+,r,x);
pushup(x);
return x;
} inline void dfs(int u){
id[cou++]=u;
for (int i=head[u];~i;i=e[i].nex)
dfs(e[i].to);
id[cou++]=-u;
} inline void init(){
memset(head,-,sizeof(head));
cnt=;
cou=;
tot=;
} inline int query(int a){
int x=L[a];
Splay(x,);
x=get_min(x);
return t[x].key;
} inline void move(int a,int b){
if (a==b) return; int x=L[a],y=R[a];
Splay(x,);
Splay(y,x); int xx=t[x].son[],yy=t[y].son[],z=;
z=get_max(xx); t[x].son[]=; t[y].son[]=;
t[xx].fa=; t[yy].fa=;
if (z!=) t[z].son[]=yy;
t[yy].fa=z; if (b==) return; if (query(b)==a){
t[x].son[]=xx; t[y].son[]=yy;
t[xx].fa=x; t[yy].fa=y;
t[z].son[]=;
return;
} int l=L[b],r;
Splay(l,);
r=get_min(t[l].son[]);
Splay(r,l);
t[r].son[]=x;
t[x].fa=r;
} int main(){
int n,q;
int x,y;
char ch[];
bool f=false;
while (scanf("%d",&n)!=EOF){
if (f) puts("");
else f=true; init(); for (int i=;i<=n;i++){
scanf("%d",&x);
addedge(x,i);
} dfs();
int k=,st=;
for (int i=;i<=*n;i++){
if (id[i]>) k++;
else k--;
if (k==) {
bulid(st,i,);
st=i+;
}
} scanf("%d",&q);
while (q--){
scanf("%s",ch);
if (ch[]=='Q') {
scanf("%d",&x);
printf("%d\n",query(x));
}
else {
scanf("%d %d",&x,&y);
move(x,y);
}
}
} return ;
}
hdu 2475 BOX (splay)的更多相关文章
- HDU 2475 BOX 动态树 Link-Cut Tree
Box Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) [Problem De ...
- Box HDU - 2475 (Splay 维护森林)
Box \[ Time Limit: 5000 ms \quad Memory Limit: 32768 kB \] 题意 给出 \(n\) 个箱子的包含关系,每次两种操作. 操作 \(1\):把 \ ...
- HDU 2475 Box
Box Time Limit: 5000ms Memory Limit: 32768KB This problem will be judged on HDU. Original ID: 247564 ...
- HDU 2475 Box 树型转线型 + 伸展树
树型转线型.第一次听说这个概念. . . , 可是曾经已经接触过了,如LCA的预处理部分和树链剖分等.可是没想到还能这么用,三者虽说有不同可是大体思想还是非常相近的,学习了. 推荐博客http://b ...
- HDOJ 题目2475 Box(link cut tree去点找祖先)
Box Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submi ...
- HDU - 2475:Box(splay维护森林)
There are N boxes on the ground, which are labeled by numbers from 1 to N. The boxes are magical, th ...
- HDU 2088 Box of Bricks
http://acm.hdu.edu.cn/showproblem.php?pid=2088 Problem Description Little Bob likes playing with his ...
- HDU 2088 Box of Bricks(脑洞)
传送门: http://acm.hdu.edu.cn/showproblem.php?pid=2088 Box of Bricks Time Limit: 1000/1000 MS (Java/Oth ...
- 『嗨威说』算法设计与分析 - 贪心算法思想小结(HDU 2088 Box of Bricks)
本文索引目录: 一.贪心算法的基本思想以及个人理解 二.汽车加油问题的贪心选择性质 三.一道贪心算法题点拨升华贪心思想 四.结对编程情况 一.贪心算法的基本思想以及个人理解: 1.1 基本概念: 首先 ...
随机推荐
- bzoj4568-幸运数字
题目 给出一棵树,每个节点上有权值\(a_i\),多次询问一条路径上选择一些点权值异或和最大值.\(n\le 2\times 10^4,q\le 2\times 10^5,0\le a_i\le 2\ ...
- bzoj1031-字符加密
环的问题,经典方法倍长串,求出后缀数组,扫一次sa,如果sa[i]小于等于n,那么就输出这个字符串结尾的位置(即s[sa[i]+n-1]). 代码 #include<cstdio> #in ...
- 【JavaScript&jQuery】省市区三级联动
HTML: <%@page import="com.mysql.jdbc.Connection"%> <%@ page language="java&q ...
- Luogu 4917 天守阁的地板(莫比乌斯反演+线性筛)
既然已经学傻了,这个题当然是上反演辣. 对于求积的式子,考虑把[gcd=1]放到指数上.一通套路后可以得到∏D∏d∏i∏j (ijd2)μ(d) (D=1~n,d|D,i,j=1~n/D). 冷静分析 ...
- 【刷题】洛谷 P3807 【模板】卢卡斯定理
题目背景 这是一道模板题. 题目描述 给定\(n,m,p( 1\le n,m,p\le 10^5)\) 求 \(C_{n+m}^{m}\ mod\ p\) 保证 \(p\) 为prime \(C\) ...
- 【单调栈】【CF5E】 Bindian Signalizing
传送门 Description 给你一个环,环上有一些点,点有点权.定义环上两点能相互看见当且仅当两点间存在一个弧使得弧上不存在一个点的点权大于着两个点.求一共有多少个点能互相看到 Input 第一行 ...
- Spring MVC POJO入参过程分析
SpringMVC确定目标方法POJO类型的入参过程 1.确认一个key: (1).若目标方法的POJO类型的参数没有使用@ModelAttribute作为修饰,则key为POJO类名第一个字母的小写 ...
- valgrind检查C/C++内存泄漏
valgrind --tool=memcheck --leak-check=full ./httptest valgrind --tool=memcheck --leak-check=full -- ...
- Qt ------ 获取 wifi 信息
QProcess:可以调用外部进程 netsh wlan show interfaces:可以查看连接哪个wifi netsh wlan show networks:显示所有可用的wifi netsh ...
- sessionStorage和localStorage的使用
不管是sessionStorage,还是localStorage,可使用的API都相同,常用的有如下几个(以localStorage为例): 保存数据:localStorage.setItem(key ...