BZOJ 1552/1506 [Cerc2007]robotic sort
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的更多相关文章
- 【BZOJ】1552/3506 [Cerc2007]robotic sort
[算法]splay [题解] splay维护序列,用权值(离散化)作为编号.每次找第i小的话直接找对应编号splay即可. 但是这样splay没有下传翻转标记?直接暴力找到路径然后从根到改结点push ...
- BZOJ 1552: [Cerc2007]robotic sort( splay )
kpm大神说可以用块状链表写...但是我不会...写了个splay.... 先离散化 , 然后splay结点加个min维护最小值 , 就可以了... ( ps BZOJ 3506 题意一样 , 双倍经 ...
- bzoj 1552: [Cerc2007]robotic sort
1552: [Cerc2007]robotic sort Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 1198 Solved: 457[Submit] ...
- [BZOJ1552][Cerc2007]robotic sort
[BZOJ1552][Cerc2007]robotic sort 试题描述 输入 输入共两行,第一行为一个整数N,N表示物品的个数,1<=N<=100000.第二行为N个用空格隔开的正整数 ...
- 【BZOJ1552】[Cerc2007]robotic sort Splay
[BZOJ1552][Cerc2007]robotic sort Description Input 输入共两行,第一行为一个整数N,N表示物品的个数,1<=N<=100000.第二行为N ...
- 【bzoj1552/3506】[Cerc2007]robotic sort splay翻转,区间最值
[bzoj1552/3506][Cerc2007]robotic sort Description Input 输入共两行,第一行为一个整数N,N表示物品的个数,1<=N<=100000. ...
- [Cerc2007]robotic sort
splay区间反转练手题 #include <iostream> #include <cstdio> #include <algorithm> using name ...
- 洛谷 P4402 BZOJ1552 / 3506 [Cerc2007]robotic sort 机械排序
FHQ_Treap 太神辣 蒟蒻初学FHQ_Treap,于是来到了这道略显板子的题目 因为Treap既满足BST的性质,又满足Heap的性质,所以,对于这道题目,我们可以将以往随机出的额外权值转化为每 ...
- 1552: [Cerc2007]robotic sort
这道题用splay写 先离散化数据保证按题目所述顺序来写 按原序作为键值建树 维护区间最小值去跑 每次将i的位置 和 n的位置x和y找出来后 将x旋转到root y旋转到x的有儿子 这时y的左子树就是 ...
随机推荐
- [leetcode]_Longest Common Prefix
问题:寻找最长公共前缀 思路:就是逐一检查每个string中的每一位,碰到不相等的时候,结束:每个string中这一位都相等,加入到common prefix中~ public String long ...
- PHP入门基础(一)——标记风格、注释、表单获取、字符串类型、变量解析
PHP标记风格: //XML风格//推荐的标记风格,可以在XML文档中使用 <?php echo '<p>XML Style</p>'; ?> //简短风格——需启 ...
- SQL Server自增长列插入指定值 -- SET IDENTITY_INSERT ON|OFF(转)
想要将值插入到自动编号(或者说是标识列,IDENTITY)中去,需要设定 SET IDENTITY_INSERT 示例: 1.首先建立一个有标识列的表:CREATE TABLE products (i ...
- Android判断横屏竖屏代码
// 判断Android当前的屏幕是横屏还是竖屏.横竖屏判断 if (this.getResources().getConfiguration().orientation == Configurati ...
- ADO.NET 结构 集中数据库联接结构
MSDN 原文出处 https://msdn.microsoft.com/zh-cn/library/27y4ybxw.aspx .NET Framework 4.6 and 4.5 其他版本 以前, ...
- 学习simple.data之进阶篇
一.结果排序 -OrderBy(升序) -OrderByDescending(降序) db.Product.All().OrderByFactoryName(); db.Product.All().O ...
- 配置visual studio code进行asp.net core rc2的开发(转载jeffreywu)
1.安装.net core sdk https://github.com/dotnet/cli#installers-and-binaries,根据你的系统选择下载 2.下载vscode的C#扩展插件 ...
- 关于EasyUI与富文本编辑器结合使用的问题(kindueditor与uueditor)
最近使用easyui玩玩项目,在结合富文本编辑器时遇到了一些问题,很多人(在网上看到)集成富文本编辑器时常常不能显示, 第一次打开编辑的时候没有问题,但是第二次打开就出错了.为此我进行了一些调试研究. ...
- python 逻辑运算符与比较运算符的差别
文章内容摘自:http://www.cnblogs.com/vamei/archive/2012/05/29/2524376.html 逻辑运算符 and, or, not 比较运算符 ==, !=, ...
- 深入理解Java String#intern() 内存模型
原文出处: codelog.me 大家知道,Java中string.intern()方法调用会先去字符串常量池中查找相应的字符串,如果字符串不存在,就会在字符串常量池中创建该字符串然后再返回. 字符串 ...