题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1890

  题目中涉及数的反转和删除操作,需要用Splay tree来实现。首先对数列排序,得到每个数在数列中的下标x。Splay tree的每个节点标记以它为根的子树是否需要反转,用到懒惰操作,保证nlogn,在每次操作的时候Push_Down()和Push_Up。在建树的时候是数的下标为节点标号建立数,如果要询问数num[i],则把num[i]在数列中的下标旋转到根节点root,size[ch[root][0]]+已经排好序的数的数目就是答案。注意,这里因为涉及到数的反转操作,因此在Splay()操作的时候,应该先Push_Down(),然后再判断旋转操作。。

 //STATUS:C++_AC_256MS_2700KB
#include <functional>
#include <algorithm>
#include <iostream>
//#include <ext/rope>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <numeric>
#include <cstring>
#include <cassert>
#include <cstdio>
#include <string>
#include <vector>
#include <bitset>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <list>
#include <set>
#include <map>
using namespace std;
//using namespace __gnu_cxx;
//define
#define pii pair<int,int>
#define mem(a,b) memset(a,b,sizeof(a))
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define PI acos(-1.0)
//typedef
typedef __int64 LL;
typedef unsigned __int64 ULL;
//const
const int N=;
const int INF=0x3f3f3f3f;
const int MOD=,STA=;
const LL LNF=1LL<<;
const double EPS=1e-;
const double OO=1e15;
const int dx[]={-,,,};
const int dy[]={,,,-};
const int day[]={,,,,,,,,,,,,};
//Daily Use ...
inline int sign(double x){return (x>EPS)-(x<-EPS);}
template<class T> T gcd(T a,T b){return b?gcd(b,a%b):a;}
template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;}
template<class T> inline T lcm(T a,T b,T d){return a/d*b;}
template<class T> inline T Min(T a,T b){return a<b?a:b;}
template<class T> inline T Max(T a,T b){return a>b?a:b;}
template<class T> inline T Min(T a,T b,T c){return min(min(a, b),c);}
template<class T> inline T Max(T a,T b,T c){return max(max(a, b),c);}
template<class T> inline T Min(T a,T b,T c,T d){return min(min(a, b),min(c,d));}
template<class T> inline T Max(T a,T b,T c,T d){return max(max(a, b),max(c,d));}
//End #define Key_value ch[ch[root][1]][0]
int pre[N],ch[N][]; //分别表示父结点,键值,左右孩子(0为左孩子,1为右孩子),根结点,结点数量
int sz[N],st[N]; //子树规模,内存池
int root,tot,top; //根节点,根节点数量,内存池容量
//题目特定数据
struct Node{
int num,idx;
}nod[N];
bool rev[N];
int n;
//debug部分copy from hh
void Treaval(int x) {
if(x) {
Treaval(ch[x][]);
printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d rev = %2d\n",x,ch[x][],ch[x][],pre[x],sz[x],rev[x]);
Treaval(ch[x][]);
}
}
void debug() {printf("%d\n",root);Treaval(root);}
//以上Debug
//新建一个结点
void NewNode(int &x,int fa,int k)
{
// if(top)x=st[--top];
// else x=++tot;
x=k;
pre[x]=fa;
sz[x]=;
rev[x]=;
ch[x][]=ch[x][]=; //左右孩子为空
} void Push_Up(int x)
{
sz[x]=sz[ch[x][]]+sz[ch[x][]]+;
} void Push_Down(int x)
{
if(rev[x]){
rev[ch[x][]]^=;
rev[ch[x][]]^=;
swap(ch[x][],ch[x][]);
rev[x]=;
}
}
//旋转,kind为1为右旋,kind为0为左旋
void Rotate(int x,int kind)
{
int y=pre[x],z=pre[y];
Push_Down(y);
Push_Down(x); //先把y的标记向下传递,再把x的标记往下传递
//类似SBT,要把其中一个分支先给父节点
ch[y][!kind]=ch[x][kind];
pre[ch[x][kind]]=y;
//如果父节点不是根结点,则要和父节点的父节点连接起来
if(z)ch[z][ch[z][]==y]=x;
pre[x]=z;
ch[x][kind]=y;
pre[y]=x;
Push_Up(y); //维护y结点,不要维护x节点,x节点会再次Push_Down,最后维护一下x节点即可
}
//Splay调整,将根为r的子树调整为goal
void Splay(int x,int goal)
{
int y,z,kind;
while(pre[x]!=goal){
//父节点即是目标位置,goal为0表示,父节点就是根结点
y=pre[x];
Push_Down(pre[y]);Push_Down(y);Push_Down(x); //设计到反转操作,要先更新,然后在判断!!
if(pre[y]==goal){
Rotate(x,ch[y][]==x);
}
else {
kind=ch[pre[y]][]==y;
//两个方向不同,则先左旋再右旋
if(ch[y][kind]==x){
Rotate(x,!kind);
Rotate(x,kind);
}
//两个方向相同,相同方向连续两次
else {
Rotate(y,kind);
Rotate(x,kind);
}
}
}
//更新根结点
Push_Up(x);
if(goal==)root=x;
}
//建树,中间结点先建立,然后分别对区间两端在左右子树建立
void BuildTree(int &x,int l,int r,int fa)
{
if(l>r)return;
int mid=(l+r)>>;
NewNode(x,fa,mid);
BuildTree(ch[x][],l,mid-,x);
BuildTree(ch[x][],mid+,r,x);
Push_Up(x);
} int cmp(Node a,Node b)
{
return a.num!=b.num?a.num<b.num:a.idx<b.idx;
} void Init()
{
root=tot=top=;
ch[root][]=ch[root][]=pre[]=sz[]=rev[]=; for(int i=;i<=n;i++){
scanf("%d",&nod[i].num);
nod[i].idx=i;
}
sort(nod+,nod+n+,cmp);
BuildTree(root,,n,);
} int Get_Max(int x)
{
Push_Down(x);
while(ch[x][]){
x=ch[x][];
Push_Down(x);
}
return x;
} void Remove()
{
if(ch[root][]==){
root=ch[root][];
pre[root]=;
}
else {
int x=Get_Max(ch[root][]);
Splay(x,root);
ch[x][]=ch[root][];
pre[ch[root][]]=x;
root=x;
pre[root]=;
Push_Up(root);
}
} int main()
{
// freopen("in.txt","r",stdin);
int i,j;
while(~scanf("%d",&n) && n)
{
Init();
for(i=;i<n;i++){
Splay(nod[i].idx,);
rev[ch[root][]]^=;
printf("%d ",i+sz[ch[root][]]);
Remove();
}
printf("%d\n",n);
}
return ;
}

HDU1890 Robotic Sort Splay tree反转,删除的更多相关文章

  1. HDU 1890 - Robotic Sort - [splay][区间反转+删除根节点]

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1890 Time Limit: 6000/2000 MS (Java/Others) Memory Li ...

  2. HDU1890 Robotic Sort[splay 序列]

    Robotic Sort Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tota ...

  3. hdu 1890 Robotic Sort(splay 区间反转+删点)

    题目链接:hdu 1890 Robotic Sort 题意: 给你n个数,每次找到第i小的数的位置,然后输出这个位置,然后将这个位置前面的数翻转一下,然后删除这个数,这样执行n次. 题解: 典型的sp ...

  4. hdu1890 Robotic Sort (splay+区间翻转单点更新)

    Problem Description Somewhere deep in the Czech Technical University buildings, there are laboratori ...

  5. BZOJ 1552: [Cerc2007]robotic sort( splay )

    kpm大神说可以用块状链表写...但是我不会...写了个splay.... 先离散化 , 然后splay结点加个min维护最小值 , 就可以了... ( ps BZOJ 3506 题意一样 , 双倍经 ...

  6. HDU 1890 Robotic Sort | Splay

    Robotic Sort Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) [Pr ...

  7. 【BZOJ1552】[Cerc2007]robotic sort Splay

    [BZOJ1552][Cerc2007]robotic sort Description Input 输入共两行,第一行为一个整数N,N表示物品的个数,1<=N<=100000.第二行为N ...

  8. 【bzoj1552/3506】[Cerc2007]robotic sort splay翻转,区间最值

    [bzoj1552/3506][Cerc2007]robotic sort Description Input 输入共两行,第一行为一个整数N,N表示物品的个数,1<=N<=100000. ...

  9. Splay Tree的删除操作

    Splay Tree的插入操作,搜索操作,和删除操作都实现了,那么就能够使用来解题了. 指针的删除操作的处理还是那么难的,非常多坎须要避开. 同一个坎还是坑了我好多次,就是指针传递的问题,什么时候须要 ...

随机推荐

  1. android webview网页控件

    一个WebView的简单例子 .在开发过程中应该注意几点: 1.AndroidManifest.xml中必须使用许可"android.permission.INTERNET",否则 ...

  2. [Unity菜鸟] 协程Coroutine

    1.协程,即协作式程序,其思想是,一系列互相依赖的协程间依次使用CPU,每次只有一个协程工作,而其他协程处于休眠状态. unity中StartCoroutine()就是协程,协程实际上是在一个线程中, ...

  3. SQL Server 2012 连接到数据库引擎

    第 1 课:连接到数据库引擎 https://msdn.microsoft.com/zh-cn/library/ms345332(v=sql.110).aspx   本课将介绍主要的工具以及如何连接并 ...

  4. windows 下 文件属性及目录列表操作

    转:http://blog.sina.com.cn/s/blog_686d0fb001012tsg.html 我们需要一个结构体和几个函数.这些函数和结构体在<io.h>的头文件中,结构体 ...

  5. fedora

    http://blog.chinaunix.net/uid-14735472-id-3486501.html 使用 http://blog.csdn.net/crystony/article/deta ...

  6. JavaBean 内省API BeanUtils工具 泛型 xml xml约束

    1 什么是JavaBean?有何特征? 1)符合特定规则的类    2)JavaBean分二类:     a)侠义的JavaBean         .私有的字段(Field)         .对私 ...

  7. Android开发之ListView-ArrayAdapter的使用

    ArrayAdapter: ArrayAdapter<String>(Context context, int resource, int textViewResourceId, Stri ...

  8. oralce索引和分区索引的使用

    oracle分区表和分区索引的本质就是将数据分段存储,包括表和索引(索引从本质上来讲也是表),表分区会将表分成多个段分别存储.由此数据查询过程改变为先根据查询条件定位分区表,然后从该表中查询数据,从而 ...

  9. 最受 Web 开发者欢迎的 NoSQL 和关系数据库

    Web应用离不开数据库,目前市场上有种类繁多数据库可供开发者选择,例如SQL.NoSQL.键值.图谱数据库等等.关于不同数据库在开发者中的受欢迎程度也是仁者见仁智者见智,但是通过统计亚马逊这样的公共云 ...

  10. Java [leetcode 35]Search Insert Position

    题目描述: Given a sorted array and a target value, return the index if the target is found. If not, retu ...