AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=1552

【分析】

  这题哇!又有翻转操作...每次要输出第几个?是吧...

  所以又要用Splay了。

  可是这道题有创新的地方,因为又有数值上的有序[取最小值],又有位置上的有序[翻转和求第几个]

  可是毕竟最小值的操作会简单很多...所以我们采用的是将位置作为Splay的节点信息。

  那么怎么快速得到最小值的位置呢?当然就是常用的push_up了...向上更新就好了。

  这里一定要注意题目所说:按照刚开始给你的顺序排序,在实现中就是数组的下标了,每次还需要比较两边最优值的大小和下标。

  然后每次选出最小值,将其转到树根,输出其左子树的大小+已经删去的最小值数目,然后将它删去,从左子树中选一个最右边的节点翻到顶上,作为新的节点。

  大致过程就是这样啦...【表示都是笔者想出来的...很开心啊...只是速度还是没有某人快啊...】

  

#include<cstdio>
#include<cstring>
#include<algorithm> using namespace std; inline int in(){
int x=,f=;char ch=getchar();
while((ch>'' || ch<'') && ch!='-') ch=getchar();
if(ch=='-') f=-,ch=getchar();
while(ch>='' && ch<='') x=x*+ch-'',ch=getchar();
return x*f;
} const int maxn=;
const int INF=0x7f7f7f7f; struct Node{
int ch[],f;
int sz,mn,lc,dt;
bool rv;
}s[maxn]; int n,rt;
int a[maxn]; void push_down(int x){
if(s[x].rv){
swap(s[x].ch[],s[x].ch[]);
s[s[x].ch[]].rv^=,s[s[x].ch[]].rv^=;
s[x].rv=;
}
}
void update(int x){
s[x].sz=s[s[x].ch[]].sz+s[s[x].ch[]].sz+;
s[x].mn=s[x].dt,s[x].lc=x;
int l,r;l=s[x].ch[],r=s[x].ch[];
if((s[l].mn<s[x].mn) || (s[l].mn==s[x].mn && s[l].lc<s[x].lc)) s[x].mn=s[l].mn,s[x].lc=s[l].lc;
if((s[r].mn<s[x].mn) || (s[r].mn==s[x].mn && s[r].lc<s[x].lc)) s[x].mn=s[r].mn,s[x].lc=s[r].lc;
} int build(int l,int r){
if(l>r) return ;
int mid=(l+r)>>;
s[mid].ch[]=build(l,mid-);
s[mid].ch[]=build(mid+,r);
if(s[mid].ch[]) s[s[mid].ch[]].f=mid;
if(s[mid].ch[]) s[s[mid].ch[]].f=mid;
s[mid].dt=a[mid];
update(mid);
return mid;
} void Rotate(int x,int k){
int y=s[x].f;s[x].f=s[y].f;
if(s[y].f) s[s[y].f].ch[y==s[s[y].f].ch[]]=x;
s[y].ch[k]=s[x].ch[k^];
if(s[x].ch[k^]) s[s[x].ch[k^]].f=y;
s[y].f=x,s[x].ch[k^]=y;
update(y),update(x);
} void Splay(int x,int gf){
int y;
while(s[x].f!=gf){
y=s[x].f;
if(s[y].f==gf) Rotate(x,x==s[y].ch[]);
else{
int z=s[y].f;
if(y==s[z].ch[]){
if(x==s[y].ch[]) Rotate(y,),Rotate(x,);else Rotate(x,),Rotate(x,);}
else{
if(x==s[y].ch[]) Rotate(y,),Rotate(x,);else Rotate(x,),Rotate(x,);}
}
}
if(!gf) rt=x;
} int Find_right(int x){
int p=x,f=-;
while(p){
push_down(p);
f=p;p=s[f].ch[];
}
return f;
} int st[maxn],tp; void up_push_down(int x){
int p=x;
while(p)
st[++tp]=p,p=s[p].f;
while(tp)
push_down(st[tp--]);
} int main(){
#ifndef ONLINE_JUDGE
freopen("1552.in","r",stdin);
freopen("1552.out","w",stdout);
#endif n=in();
for(int i=;i<=n;i++) a[i]=in();
s[].mn=INF;s[].lc=-;
rt=build(,n);
int x;
for(int i=;i<=n;i++){
up_push_down(s[rt].lc);
Splay(s[rt].lc,);
printf("%d",s[s[rt].ch[]].sz+i);
if(i!=n) printf(" ");
s[s[rt].ch[]].rv^=;
if(!s[rt].ch[]){
s[s[rt].ch[]].f=;rt=s[rt].ch[];
}
else{
x=Find_right(s[rt].ch[]);
Splay(x,rt);
s[x].f=;
s[x].ch[]=s[rt].ch[];
if(s[rt].ch[])
s[s[rt].ch[]].f=x;
update(x);rt=x;
}
}
return ;
}

BZOJ 1552/1506 [Cerc2007]robotic sort的更多相关文章

  1. 【BZOJ】1552/3506 [Cerc2007]robotic sort

    [算法]splay [题解] splay维护序列,用权值(离散化)作为编号.每次找第i小的话直接找对应编号splay即可. 但是这样splay没有下传翻转标记?直接暴力找到路径然后从根到改结点push ...

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

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

  3. bzoj 1552: [Cerc2007]robotic sort

    1552: [Cerc2007]robotic sort Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1198  Solved: 457[Submit] ...

  4. [BZOJ1552][Cerc2007]robotic sort

    [BZOJ1552][Cerc2007]robotic sort 试题描述 输入 输入共两行,第一行为一个整数N,N表示物品的个数,1<=N<=100000.第二行为N个用空格隔开的正整数 ...

  5. 【BZOJ1552】[Cerc2007]robotic sort Splay

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

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

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

  7. [Cerc2007]robotic sort

    splay区间反转练手题 #include <iostream> #include <cstdio> #include <algorithm> using name ...

  8. 洛谷 P4402 BZOJ1552 / 3506 [Cerc2007]robotic sort 机械排序

    FHQ_Treap 太神辣 蒟蒻初学FHQ_Treap,于是来到了这道略显板子的题目 因为Treap既满足BST的性质,又满足Heap的性质,所以,对于这道题目,我们可以将以往随机出的额外权值转化为每 ...

  9. 1552: [Cerc2007]robotic sort

    这道题用splay写 先离散化数据保证按题目所述顺序来写 按原序作为键值建树 维护区间最小值去跑 每次将i的位置 和 n的位置x和y找出来后 将x旋转到root y旋转到x的有儿子 这时y的左子树就是 ...

随机推荐

  1. 线程池(C#)

    转自:http://blog.sina.com.cn/s/blog_494305f30100ryw7.html 在这里你可以学到Microsoft研究CLR实现线程池的原理机制,从而更灵活的处理CLR ...

  2. 安卓手机的touchend事件不触发问题

    问题描述 $(document).on("touchstart touchmove",".btn-highlight",function(event){ $(t ...

  3. GoldenGate中使用FILTER,COMPUTE 和SQLEXEC命令

    本文主要介绍OGG中一些过滤或计算函数的用法,以及sqlexec的基本用法 SQLPREDICATE 在使用OGG初始化时,可以添加此参数到extract中,用于选择符合条件的记录,下面是OGG官方文 ...

  4. while循环中不支持循环使用curl

    <?php $link = mysql_connect('localhost', 'sms', 'sms'); mysql_select_db('sms', $link); mysql_quer ...

  5. android 特效UI实现

    弧形菜单 https://github.com/daCapricorn/ArcMenu

  6. Python基础 第二天

    1.http://www.cnblogs.com/beer/p/5672678.html requests和beautifulsoup

  7. Learning Scrapy笔记(三)- Scrapy基础

    摘要:本文介绍了Scrapy的基础爬取流程,也是最重要的部分 Scrapy的爬取流程 Scrapy的爬取流程可以概括为一个方程式:UR2IM,其含义如下图所示 URL:Scrapy的运行就从那个你想要 ...

  8. 【Django】Apache上运行多个Django项目

    运行单个项目的步骤参考:这里 1 安装环境 操作系统:Ubuntu 12.04 LTS 32 位(安装在VMware虚拟机中) python 版本: Python 2.7.3 Django版本 > ...

  9. deep learning学习环境Theano安装(win8+win7)

    官网安装说明Installing Theano:http://deeplearning.net/software/theano/install.html#alternative-anacondace ...

  10. C# Sql 触发器

    触发器是一种特殊类型的存储过程,它不同于之前的我们介绍的存储过程.触发器主要是通过事件进行触发被自动调用执行的.而存储过程可以通过存储过程的名称被调用. Ø 什么是触发器 触发器对表进行插入.更新.删 ...