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序中的 ...
随机推荐
- bootstrap 学习笔记(3)---- 代码
这节讲的是代码: 1.基本实例 <code></code> <pre></pre> <kbd></kbd> 应用如下 1.Fo ...
- AtCoder Grand Contest 007 E:Shik and Travel
题目传送门:https://agc007.contest.atcoder.jp/tasks/agc007_e 题目翻译 现在有一个二叉树,除了叶子每个结点都有两个儿子.这个二叉树一共有\(m\)个叶子 ...
- SIP呼叫流程典型流程图解及其详细解释
目录(?)[+] 1.注册流程: 2.注销流程: 3. 基本呼叫建立过程: 4. 会话更改流程: 5. 正常呼叫释放过程: 6. 被叫忙呼叫释放: 7.被叫无应答流程一: 8.被叫无应答流程二: ...
- 管理SSIS 日志
转自:http://www.cnblogs.com/biwork/p/biworklog.html 一直准备写这么一篇有关 SSIS 日志系统的文章,但是发现很难一次写的很完整.因为这篇文章的内容可扩 ...
- JS获取元素的offsetTop,offsetLeft等相关属性
1. obj.clientWidth //获取元素的宽度 obj.clientHeight //元素的高度 obj.offsetLeft //元素相对于父元素的left obj.offsetTop / ...
- 1.8 Hive运行日志配置和查看
一.配置文件 1.重命名配置文件 # 把/opt/modules/hive-0.13.1/conf/hive-log4j.properties.template重命名为hive-log4j.prope ...
- js的call()通俗解释
var x = "我是全局变量"; //定义全局变量x function a(){ //定义函数类结构a this.x = "我是在函数类结构a中声明的哦"; ...
- UVaLive 6853 Concert Tour (DP)
题意:给定 n 个城市,m 个月,表示要在这 n 个城市连续 m 个月开演唱会,然后给定每个月在每个城市开演唱会能获得的利润,然后就是演唱会在不同城市之间调动所要的费用, 问你,怎么安排这 n 个演唱 ...
- 原创|高逼格企业级MySQL数据库备份方案,原来是这样....
很多人,这里说的是运维工程师们,一提到写某某方案,很是头疼.不是上某度一统搜索,就是同样一句话在N个群全部群发一遍:“有没有某某方案,可以共享一下的吗??求助,各位大佬们”,估计十有八九,全部石沉大海 ...
- HDU-2602 Bone Collector——01背包
首先输入一个数字代表有n个样例 接下来的三行 第一行输入n 和 v,代表n块骨头,背包体积容量为v. 第二行输入n块骨头的价值 第三行输入n块骨头的体积 问可获得最大的价值为多少 核心:关键在于d ...