hdu2475Box(splay树形转线性)
推荐一篇帖子
http://blog.csdn.net/lyhypacm/article/details/6734748
这题暴力不可行主要是因为这颗树可能极度不平衡,不能用并查集是不能路径压缩,这样时间复杂度是很高的。
可以用伸展树主要是因为它的伸展性,每次操作后可以通过伸展使这棵树更好的保持平衡。
这题还是值得记录一下的,从早上做到了晚上,
第一次错误,定义了全局的n以及局部的n使得取得结果不正确,以后还是统一习惯,要么写在全局要么写在局部。
第二次错误,vector初始化没有初始到0导致后面的数据跑不动,以后初始化的操作都从0开始。
第三次错误,debug了n久,建树的时候误把根节点的父亲节点写成了根,应该是0,自以为不会出错的地方也要认真检查。
#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stdlib.h>
#include<vector>
#include<cmath>
#include<queue>
#include<set>
#include<stack>
using namespace std;
#define N 100010
#define LL long long
#define INF 0xfffffff
const double eps = 1e-;
const double pi = acos(-1.0);
const double inf = ~0u>>;
int n,po[N];
vector<int>ed[N];
vector<int>dd; struct splay_tree
{
int pre[N];
int ch[N][];
int root,tot,num;
int key[N];
// void dfs(int x)
// {
// if(x)
// {
// dfs(ch[x][0]);
// printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size=%2d,key=%2d\n",
// x,ch[x][0],ch[x][1],pre[x],size[x],key[x]);
// dfs(ch[x][1]);
// }
// }
// void debug()
// {
// printf("root:%d\n",root);
// dfs(root);
// }
//以上用于debug*/
void newnode(int &x,int v,int fa)//新建一结点
{
x = ++tot;
ch[x][]=ch[x][] = ;
pre[x] = fa;
key[x] = v;
po[v] = x;
}
void pushup(int w)//由儿子更新其父亲
{
}
void rotate(int r,int kind)//旋转操作,根据kind进行左旋和右旋
{
int y = pre[r];
ch[y][!kind] = ch[r][kind];
pre[ch[r][kind]] = y;
if(pre[y])
{
ch[pre[y]][ch[pre[y]][]==y] = r;
}
pre[r] = pre[y];
ch[r][kind] = y;
pre[y] = r;
pushup(y);
pushup(r);
}
void splay(int r,int goal)//将r结点旋至goal下
{
while(pre[r]!=goal)
{
if(pre[pre[r]]==goal)
{
rotate(r,ch[pre[r]][]==r);
}
else
{
int y = pre[r];
int kind = (ch[pre[y]][]==y);
if(ch[y][kind]==r)
{
rotate(r,!kind);
rotate(r,kind);
}
else
{
rotate(y,kind);
rotate(r,kind);
}
}
}
pushup(r);
if(goal==) root = r;
}
int get_min(int x)
{
while(ch[x][])
x = ch[x][];
return x;
}
int get_max(int x)
{
while(ch[x][])
x = ch[x][];
return x;
}
void update(int x,int y) //更新区间信息
{
int l = po[x],r = po[x+n];
splay(l,);
splay(r,);
int ll = ch[l][];
int rr = ch[r][];
pre[ll] = pre[rr] = ;
ch[r][] = ch[l][] = ; int tll = get_max(ll);
if(tll!=)
ch[tll][] = rr;
pre[rr] = tll; if(y==) return ;
if(query(y)==x)
{
ch[r][] = rr;
ch[l][] = ll;
pre[ll] = l;
pre[rr] = r;
ch[tll][] = ;
pre[] = ;
return ;
} if(rr!=) splay(rr,);
int tt = po[y];
splay(tt,);
int tq = get_min(ch[tt][]);
splay(tq,tt);
ch[tq][] = r;
pre[r] = tq;
}
int query(int x)//询问l,r区间,将第l-1个结点旋自根,第r+1个结点旋自根的有儿子,
{
splay(po[x],);
int k = get_min(po[x]);
return key[k];
}
void build(int &x,int l,int r,int fa)
{
int m = (l+r)>>;
if(l>r) return ;
newnode(x,dd[m],fa);
build(ch[x][],l,m-,x);
build(ch[x][],m+,r,x);
pushup(x);
}
void init()
{
root = tot = ;
memset(ch,,sizeof(ch));
memset(pre,,sizeof(pre));
memset(key,,sizeof(key));
memset(po,,sizeof(po));
}
} SP;
void dfs(int u)
{
int i;
dd.push_back(u);
for(i = ; i < ed[u].size(); i++)
{
int v = ed[u][i];
dfs(v);
}
dd.push_back(u+n);
}
int main()
{
int i;
int q;
int mark = false;
while(scanf("%d",&n)!=EOF)
{
if(mark)
puts("");
else
mark = true;
SP.init();
for(i = ; i <= n; i++)
{
ed[i].clear();
}
dd.clear();
for(i = ; i <= n; i++)
{
int x;
scanf("%d",&x);
ed[x].push_back(i);
}
dfs();
int o = ;
scanf("%d",&q);
stack<int>st;
for(i = ; i < dd.size()- ; i++)
{
int x = dd[i];
if(x<=n) st.push(x);
else st.pop();
if(st.empty())
{
SP.build(SP.root,o,i,);
o = i+;
}
}
int stt = ;
while(q--)
{
char sq[];
int x,y;
scanf("%s",sq);
if(sq[]=='Q')
{
scanf("%d",&x);
printf("%d\n",SP.query(x));
}
else
{
scanf("%d%d",&x,&y);
SP.update(x,y);
}
}
}
return ;
}
hdu2475Box(splay树形转线性)的更多相关文章
- Codeforces 570D - Tree Requests【树形转线性,前缀和】
http://codeforces.com/contest/570/problem/D 给一棵有根树(50w个点)(指定根是1号节点),每个点上有一个小写字母,然后有最多50w个询问,每个询问给出x和 ...
- CodeForces 466E Information Graph --树形转线性+并查集
题意:有三种操作: 1.新增一条边从y连向x,此前x没有父节点 2.x接到一份文件,(文件标号逐次递增),然后将这份文件一路上溯,让所有上溯的节点都接到这份文件 3.查询某个节点x是否接到过文件F 解 ...
- 线性结构与树形结构相互转换(ES6实现)
前言 当树形结构的层级越来越深时,操作某一节点会变得越来越费劲,维护成本不断增加.所以线性结构与树形的相互转换变得异常重要! 首先,我们约定树形结构如下: node = { id: number, / ...
- 第一阶段:Java内功秘籍-线性表
前言 为什么要学习数据结构与算法,如果你学会了做安卓,javaweb,前端等,都是你的武功秘籍,但是如果你的内功不够好,再厉害的功夫也是白费. 数据结构和算法:什么是数据结构,什么是数据,在计算机内部 ...
- RMQ 与 LCA-ST算法
RMQ算法 区间求最值的算法,用区间动态规划(nlogn)预处理,查询O(1) http://blog.csdn.net/y990041769/article/details/38405063 (PO ...
- 树链剖分详解(洛谷模板 P3384)
洛谷·[模板]树链剖分 写在前面 首先,在学树链剖分之前最好先把 LCA.树形DP.DFS序 这三个知识点学了 emm还有必备的 链式前向星.线段树 也要先学了. 如果这三个知识点没掌握好的话,树链剖 ...
- Kuangbin 带你飞-线段树专题 题解
HDU 1166 敌兵布阵 单调更新区间查询和 #include <map> #include <set> #include <list> #include < ...
- git使用笔记-基础篇
git使用手册:https://git-scm.com/book/zh/v1/ 一.分支 1.查看所有本地分支 git branch 2.查看所有本地分支和远程分支 git branch -a 3.查 ...
- UVA10410 TreeReconstruction 树重建 (dfs,bfs序的一些性质,以及用栈处理递归 )
题意,给你一颗树的bfs序和dfs序,结点编号小的优先历遍,问你可能的一种树形: 输出每个结点的子结点. 注意到以下事实: (1)dfs序中一个结点的子树结点一定是连续的. (2)bfs,dfs序中的 ...
随机推荐
- Centos下Docker安装与使用的相关命令
sudo yum install -y yum-utils device-mapper-persistent-data lvm2 systemctl docker status yum-config- ...
- http://www.cnblogs.com/yaozhenfa/archive/2015/06/14/4574898.html
笔者这里采用的是mongoDB官网推荐使用.net驱动: http://mongodb.github.io/mongo-csharp-driver/2.0/getting_started/quick_ ...
- CISCO-路由器交换机密码恢复
路由器密码恢复: 准备工作:一台PC跟一台路由器用console线相连 工作原理:如果忘记密码被锁在路由器外,通过修复寄存器值来进行修复 默认的寄存器值为0x2102(关闭的),若要恢复口令需要开启这 ...
- live555 基本类之间的关系
live555 中存在这5个最基本的类.每个类中都拥有一个BasicUsageEnvironment. 这是这几个类之间的相互关系. MediaSession可以拥有多个subsession.
- 2014年将会受欢迎的IT技能--你有多少哪?
据国外媒体报道,据Global Knowledge等十几家研究机构发布的2014年IT技能和薪金调查报告显示,2014年最受欢迎的十大IT技能如下: 1.编程与应用开发 据美国劳工统计局称,开发者和程 ...
- Python的中文处理
一.使用中文字符 在python源码中如果使用了中文字符,运行时会有错误,解决的办法是在源码的开头部分加入字符编码的声明,下面是一个例子: #!/usr/bin/env python # -*- co ...
- CV_Assert
转:http://blog.csdn.net/ding977921830/article/details/46376847 Checks a condition at runtime and thro ...
- CF-805C
C. Find Amir time limit per test 1 second memory limit per test 256 megabytes input standard input o ...
- python 之 staticmethod,classmethod,property的区别
绑定方法和非绑定方法: 普通def定义的都是绑定给对象的方法,对象调用时会自动传入对象本事,而类调用时需手动传入对象. 加上@classmethod装饰器就是绑定给类的方法,会自动传类本身 加上@st ...
- HTML中 &emsp等空格的区别
HTML提供了5种空格实体(space entity),它们拥有不同的宽度,非断行空格( )是常规空格的宽度,可运行于所有主流浏览器.其他几种空格( )在不同浏览器中宽度各异. ...