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. 【CodeForces】913 E. Logical Expression

    [题目]E. Logical Expression [题意]令x=11110000(2),y=11001100(2),z=10101010(2),n次询问,每次要求用[与][或][非][括号]构成含至 ...

  2. Verilog笔记.6.FIFO

    FIFO,First In First Out ,是一种先进先出的数据缓存器. 没有外部读写地址线,只能顺序写入数据,顺序的读出数据, 其数据地址由内部读写指针自动加1完成. 不能像普通存储器那样可以 ...

  3. pycharm设置字体大小

    pycharm 是很好的一个IDE,在windows下,和macOS下,都能很好的运行.唯一缺点是启动慢. 默认字体太小,在mac下,需要瞪大24K氪金狗眼才能看清. 为了保护好眼睛,我们需要把字体调 ...

  4. bootstrap分页查询传递中文参数到后台(get方式提交)

    <!--分页 --> <div style="width: 380px; margin: 0 auto; margin-top: 50px;"> <u ...

  5. (1)剑指Offer之斐波那契数列问题和跳台阶问题

    一 斐波那契数列 题目描述: 大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项. n<=39 问题分析: 可以肯定的是这一题通过递归的方式是肯定能做出来,但是这样会有 ...

  6. 41、和为S的连续正数序列

    一.题目 小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100.但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数).没多久,他 ...

  7. Fedora8 U盘安装

    (一)分区 在XP下"我的电脑“管理功能,对硬盘分区,目的是从逻辑分区中拿出20G空间,分成3个盘(必须为逻辑盘): (1)512MB   用作Linux swap分区: (2)200MB  ...

  8. 【转载】如何解决failed to push some refs to git

    在使用git 对源代码进行push到gitHub时可能会出错,信息如下   此时很多人会尝试下面的命令把当前分支代码上传到master分支上. $ git push -u origin master ...

  9. 深入解析Mysql 主从同步延迟原理及解决方案

    MySQL的主从同步是一个很成熟的架构,优点为:①在从服务器可以执行查询工作(即我们常说的读功能),降低主服务器压力;②在从主服务器进行备份,避免备份期间影响主服务器服务;③当主服务器出现问题时,可以 ...

  10. Getting Started with Django Rest Framework and AngularJS

    转载自:http://blog.kevinastone.com/getting-started-with-django-rest-framework-and-angularjs.html A ReST ...