Splay

与之前不同的是如果你仅仅是翻转左右区间的话可以在find里面做因为对他有影响的子树在做之前一定在他的上面从上到下搜索的过程可以把rever做了。

但这道题要求我们输出转换之前的,因此不能保证之前的rev标记都已执行完因此就要从上到下做一遍。

By:大奕哥

 #include<bits/stdc++.h>
using namespace std;
const int N=1e5+;
int fa[N],c[N][],pos[N],rev[N],mn[N],w[N],size[N],n,m,rt;
struct node
{
int pos,v;
bool operator<(const node &b)const {
if(v==b.v)return pos<b.pos;
return v<b.v;
}
}a[N];
void pushdown(int x)
{
if(rev[x])rev[c[x][]]^=,rev[c[x][]]^=,rev[x]^=,swap(c[x][],c[x][]);
mn[x]=w[x];pos[x]=x;
if(mn[c[x][]]<mn[x])mn[x]=mn[c[x][]],pos[x]=pos[c[x][]];
if(mn[c[x][]]<mn[x])mn[x]=mn[c[x][]],pos[x]=pos[c[x][]];
size[x]=size[c[x][]]+size[c[x][]]+;
}
void rotate(int x,int &k)
{
int y=fa[x],z=fa[y];
int l=(c[y][]==x);int r=l^;
if(y==k)k=x;else c[z][c[z][]==y]=x;
fa[x]=z;fa[y]=x;fa[c[x][r]]=y;
c[y][l]=c[x][r];c[x][r]=y;
pushdown(y);pushdown(x);
}
int s[N],top;
void splay(int x,int &k)
{
top=;
for(int i=x;i;i=fa[i])s[++top]=i;
for(int i=top;i;--i)pushdown(s[i]);
while(x!=k)
{
int y=fa[x],z=fa[y];
if(y!=k)
{
if(x==c[y][]^y==c[z][])rotate(x,k);
else rotate(y,k);
}
rotate(x,k);
}
}
int find(int x,int k)
{
if(!x)return ;pushdown(x);
if(size[c[x][]]+==k)return x;
else if(size[c[x][]]+>k)return find(c[x][],k);
else return find(c[x][],k-size[c[x][]]-);
}
int query(int l,int r)
{
int x=find(rt,l),y=find(rt,r+);
splay(x,rt);splay(y,c[x][]);
return pos[c[y][]];
}
void rever(int l,int r)
{
int x=find(rt,l),y=find(rt,r+);
splay(x,rt);splay(y,c[x][]);
int z=c[y][];
rev[z]^=;
return;
}
void build(int l,int r,int f){
if(l>r)return;
int mid=l+r>>;
fa[mid]=f;c[f][mid>=f]=mid;
w[mid]=mn[mid]=a[mid].v;
if(l==r)
{
rev[mid]=;size[mid]=;pushdown(mid);return;
}
build(l,mid-,mid);build(mid+,r,mid);
pushdown(mid);
return;
}
bool cmp(node aa,node bb){
return aa.pos<bb.pos;
}
int ans[N];
int main()
{
scanf("%d",&n);
build(,n+,);rt=(n+)>>;mn[]=a[].v=a[n+].v=1e9;
for(int i=;i<=n+;++i)scanf("%d",&a[i].v);
for(int i=;i<=n;++i)a[i+].pos=i;
sort(a+,a+n+);
for(int i=;i<=n;++i)a[i+].v=i;
sort(a+,a+n+,cmp);
build(,n+,);
rt=(n+)>>;
for(int i=;i<=n;++i)
{
int x=query(i,n);
splay(x,rt);
ans[i]=size[c[x][]];
rever(i,ans[i]);
}
for(int i=;i<n;++i)
{
printf("%d ",ans[i]);
}
printf("%d",ans[n]);
return ;
}

这个是标准的按照序列中的位置建树,每次splay之前要query一下。跑了3000ms,后来又在网上找了一种写法,直接按照权值建图,查找就直接splay对应的标号即可,2000ms。

 #include<bits/stdc++.h>
using namespace std;
const int N=1e5+;
int fa[N],c[N][],pos[N],rev[N],mn[N],w[N],size[N],n,m,rt;
struct node
{
int pos,v;
bool operator<(const node &b)const {
if(v==b.v)return pos<b.pos;
return v<b.v;
}
}a[N];
bool cmp(node aa,node bb){
return aa.pos<bb.pos;
}
void pushdown(int x)
{
if(rev[x])rev[c[x][]]^=,rev[c[x][]]^=,rev[x]^=,swap(c[x][],c[x][]);
mn[x]=w[x];pos[x]=x;
if(mn[c[x][]]<mn[x])mn[x]=mn[c[x][]],pos[x]=pos[c[x][]];
if(mn[c[x][]]<mn[x])mn[x]=mn[c[x][]],pos[x]=pos[c[x][]];
size[x]=size[c[x][]]+size[c[x][]]+;
}
void rotate(int x,int &k)
{
int y=fa[x],z=fa[y];
int l=(c[y][]==x);int r=l^;
if(y==k)k=x;else c[z][c[z][]==y]=x;
fa[x]=z;fa[y]=x;fa[c[x][r]]=y;
c[y][l]=c[x][r];c[x][r]=y;
pushdown(y);pushdown(x);
}
int s[N],top;
void splay(int x,int &k)
{
top=;
for(int i=x;i;i=fa[i])s[++top]=i;
for(int i=top;i;--i)pushdown(s[i]);
while(x!=k)
{
int y=fa[x],z=fa[y];
if(y!=k)
{
if(x==c[y][]^y==c[z][])rotate(x,k);
else rotate(y,k);
}
rotate(x,k);
}
}
int find(int x,int k)
{
if(!x)return ;pushdown(x);
if(size[c[x][]]+==k)return x;
else if(size[c[x][]]+>k)return find(c[x][],k);
else return find(c[x][],k-size[c[x][]]-);
}
void rever(int l,int r)
{
int x=find(rt,l),y=find(rt,r+);
splay(x,rt);splay(y,c[x][]);
int z=c[y][];
rev[z]^=;
return;
}
void build(int l,int r,int f){
if(l>r)return;
int mid=l+r>>;
int now=a[mid].v,last=a[f].v;
fa[now]=last;c[last][mid>=f]=now;
if(l==r)
{
rev[now]=;size[now]=;return;
}
build(l,mid-,mid);build(mid+,r,mid);
pushdown(now);
return;
}
int ans[N];
int main()
{
scanf("%d",&n);
rt=(n+)>>;mn[]=1e9;
for(int i=;i<=n+;++i)scanf("%d",&a[i].v);
for(int i=;i<=n;++i)a[i+].pos=i;
sort(a+,a+n+);
for(int i=;i<=n+;++i)a[i].v=i;a[].v=;a[n+].v=n+;
sort(a+,a+n+,cmp);
build(,n+,);
rt=a[(n+)>>].v;
for(int i=;i<=n;++i)
{
splay(i+,rt);
ans[i]=size[c[rt][]];
rever(i,ans[i]);
}
for(int i=;i<n;++i)
{
printf("%d ",ans[i]);
}
printf("%d",ans[n]);
return ;
}

BZOJ1552/3506 [Cerc2007]robotic sort的更多相关文章

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

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

  2. 【BZOJ1552】[Cerc2007]robotic sort Splay

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

  3. 【BZOJ-1552&3506】robotic sort&排序机械臂 Splay

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

  4. 【bzoj1552】[Cerc2007]robotic sort

    题目描述 输入 输入共两行,第一行为一个整数N,N表示物品的个数,1<=N<=100000.第二行为N个用空格隔开的正整数,表示N个物品最初排列的编号. 输出 输出共一行,N个用空格隔开的 ...

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

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

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

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

  7. [BZOJ1552][Cerc2007]robotic sort

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

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

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

  9. bzoj 1552: [Cerc2007]robotic sort

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

随机推荐

  1. DIV+CSS制作斜线效果记录

    DIV+CSS 斜线效果很简单,只需设置一下CSS Border 的边框就能有斜线效果.代码分享给大家,你可以自己变通. 提示要注意两点:1.DIV宽高的定义.2.DIV在 IE6 中默认是有高度的. ...

  2. 【CodeForces】913 C. Party Lemonade

    [题目]C. Party Lemonade [题意]给定n个物品,第i个物品重量为2^(i-1)价值为ci,每个物品可以无限取,求取总重量>=L的最小代价.1<=30<=n,1< ...

  3. js、php本周第一天和本周最后一天

    PHP:本周一 echo date('Y-m-d',(time()-((date('w')==0?7:date('w'))-1)*24*3600)); //w为星期几的数字形式,这里0为周日 本周日 ...

  4. /i,/m,/s,/x,/A,/s,/U,/x,/j,/u 等正则修饰符用法~

    i (PCRE_CASELESS) 如果设置了这个修饰符,模式中的字母会进行大小写不敏感匹配. m (PCRE_MULTILINE) 默认情况下,PCRE 认为目标字符串是由单行字符组成的(然而实际上 ...

  5. ASP.NET EF 使用LinqPad 快速学习Linq

    使用LinqPad这个工具可以很快学习并掌握linq[Language Integrated Query] linqPad官方下载地址:http://www.linqpad.net/ linqPad4 ...

  6. localStorage H5本地存储

    域内安全.永久保存.即客户端或浏览器中来自同一域名的所有页面都可访问localStorage数据且数据除了删除否则永久保存,但客户端或浏览器之间的数据相互独立. <!doctype html&g ...

  7. perl6 登录phpmyadmin

    use HTTP::UserAgent; my $ua = HTTP::UserAgent.new; my $url = 'http://localhost/phpMyAdmin/index.php' ...

  8. UBIFS学习笔记

    在做项目的时候,发现flash芯片有异常现象,经过打印分析,发现是UBIFS方面设置有一些问题,经过查阅一部分资料,最终得到问题的答案. 在解决问题的过程中,发现打印信息比较重要,但网上并没有直接的相 ...

  9. Asia-Dhaka 2017

    Asia-Dhaka 2017 A - Brick Walls 题目描述:如下图,编坐标与路径,给出两个坐标,问两个坐标的最短距离是多少. solution 先阶梯型地走,然后注意"中&qu ...

  10. 以太坊go-ethereum项目源码本地环境搭建

    如果要深入了解go-ethereum项目的实现与机制,看源代码是必不可少的.今天这篇博客就简单介绍一下如何在本地搭建项目的开发环境. GO语言环境搭建 以win8为例,访问地址https://gola ...