BZOJ1552/3506 [Cerc2007]robotic sort

Splay

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

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

By:大奕哥

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 const int N=1e5+10;
  4 int fa[N],c[N][2],pos[N],rev[N],mn[N],w[N],size[N],n,m,rt;
  5 struct node
  6 {
  7     int pos,v;
  8     bool operator<(const node &b)const {
  9         if(v==b.v)return pos<b.pos;
 10         return v<b.v;
 11     }
 12 }a[N];
 13 void pushdown(int x)
 14 {
 15     if(rev[x])rev[c[x][0]]^=1,rev[c[x][1]]^=1,rev[x]^=1,swap(c[x][0],c[x][1]);
 16     mn[x]=w[x];pos[x]=x;
 17     if(mn[c[x][0]]<mn[x])mn[x]=mn[c[x][0]],pos[x]=pos[c[x][0]];
 18     if(mn[c[x][1]]<mn[x])mn[x]=mn[c[x][1]],pos[x]=pos[c[x][1]];
 19     size[x]=size[c[x][0]]+size[c[x][1]]+1;
 20 }
 21 void rotate(int x,int &k)
 22 {
 23     int y=fa[x],z=fa[y];
 24     int l=(c[y][1]==x);int r=l^1;
 25     if(y==k)k=x;else c[z][c[z][1]==y]=x;
 26     fa[x]=z;fa[y]=x;fa[c[x][r]]=y;
 27     c[y][l]=c[x][r];c[x][r]=y;
 28     pushdown(y);pushdown(x);
 29 }
 30 int s[N],top;
 31 void splay(int x,int &k)
 32 {
 33     top=0;
 34     for(int i=x;i;i=fa[i])s[++top]=i;
 35     for(int i=top;i;--i)pushdown(s[i]);
 36     while(x!=k)
 37     {
 38         int y=fa[x],z=fa[y];
 39         if(y!=k)
 40         {
 41             if(x==c[y][0]^y==c[z][0])rotate(x,k);
 42             else rotate(y,k);
 43         }
 44         rotate(x,k);
 45     }
 46 }
 47 int find(int x,int k)
 48 {
 49     if(!x)return 0;pushdown(x);
 50     if(size[c[x][0]]+1==k)return x;
 51     else if(size[c[x][0]]+1>k)return find(c[x][0],k);
 52     else return find(c[x][1],k-size[c[x][0]]-1);
 53 }
 54 int query(int l,int r)
 55 {
 56     int x=find(rt,l),y=find(rt,r+2);
 57     splay(x,rt);splay(y,c[x][1]);
 58     return pos[c[y][0]];
 59 }
 60 void rever(int l,int r)
 61 {
 62     int x=find(rt,l),y=find(rt,r+2);
 63     splay(x,rt);splay(y,c[x][1]);
 64     int z=c[y][0];
 65     rev[z]^=1;
 66     return;
 67 }
 68 void build(int l,int r,int f){
 69     if(l>r)return;
 70     int mid=l+r>>1;
 71     fa[mid]=f;c[f][mid>=f]=mid;
 72     w[mid]=mn[mid]=a[mid].v;
 73     if(l==r)
 74     {
 75         rev[mid]=0;size[mid]=1;pushdown(mid);return;
 76     }
 77     build(l,mid-1,mid);build(mid+1,r,mid);
 78     pushdown(mid);
 79     return;
 80 }
 81 bool cmp(node aa,node bb){
 82     return aa.pos<bb.pos;
 83 }
 84 int ans[N];
 85 int main()
 86 {
 87     scanf("%d",&n);
 88     build(1,n+2,0);rt=(n+3)>>1;mn[0]=a[1].v=a[n+2].v=1e9;
 89     for(int i=2;i<=n+1;++i)scanf("%d",&a[i].v);
 90     for(int i=1;i<=n;++i)a[i+1].pos=i;
 91     sort(a+2,a+n+2);
 92     for(int i=1;i<=n;++i)a[i+1].v=i;
 93     sort(a+2,a+n+2,cmp);
 94     build(1,n+2,0);
 95     rt=(n+3)>>1;
 96     for(int i=1;i<=n;++i)
 97     {
 98         int x=query(i,n);
 99         splay(x,rt);
100         ans[i]=size[c[x][0]];
101         rever(i,ans[i]);
102     }
103     for(int i=1;i<n;++i)
104     {
105         printf("%d ",ans[i]);
106     }
107     printf("%d",ans[n]);
108     return 0;
109 }

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

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 const int N=1e5+10;
  4 int fa[N],c[N][2],pos[N],rev[N],mn[N],w[N],size[N],n,m,rt;
  5 struct node
  6 {
  7     int pos,v;
  8     bool operator<(const node &b)const {
  9         if(v==b.v)return pos<b.pos;
 10         return v<b.v;
 11     }
 12 }a[N];
 13 bool cmp(node aa,node bb){
 14     return aa.pos<bb.pos;
 15 }
 16 void pushdown(int x)
 17 {
 18     if(rev[x])rev[c[x][0]]^=1,rev[c[x][1]]^=1,rev[x]^=1,swap(c[x][0],c[x][1]);
 19     mn[x]=w[x];pos[x]=x;
 20     if(mn[c[x][0]]<mn[x])mn[x]=mn[c[x][0]],pos[x]=pos[c[x][0]];
 21     if(mn[c[x][1]]<mn[x])mn[x]=mn[c[x][1]],pos[x]=pos[c[x][1]];
 22     size[x]=size[c[x][0]]+size[c[x][1]]+1;
 23 }
 24 void rotate(int x,int &k)
 25 {
 26     int y=fa[x],z=fa[y];
 27     int l=(c[y][1]==x);int r=l^1;
 28     if(y==k)k=x;else c[z][c[z][1]==y]=x;
 29     fa[x]=z;fa[y]=x;fa[c[x][r]]=y;
 30     c[y][l]=c[x][r];c[x][r]=y;
 31     pushdown(y);pushdown(x);
 32 }
 33 int s[N],top;
 34 void splay(int x,int &k)
 35 {
 36     top=0;
 37     for(int i=x;i;i=fa[i])s[++top]=i;
 38     for(int i=top;i;--i)pushdown(s[i]);
 39     while(x!=k)
 40     {
 41         int y=fa[x],z=fa[y];
 42         if(y!=k)
 43         {
 44             if(x==c[y][0]^y==c[z][0])rotate(x,k);
 45             else rotate(y,k);
 46         }
 47         rotate(x,k);
 48     }
 49 }
 50 int find(int x,int k)
 51 {
 52     if(!x)return 0;pushdown(x);
 53     if(size[c[x][0]]+1==k)return x;
 54     else if(size[c[x][0]]+1>k)return find(c[x][0],k);
 55     else return find(c[x][1],k-size[c[x][0]]-1);
 56 }
 57 void rever(int l,int r)
 58 {
 59     int x=find(rt,l),y=find(rt,r+2);
 60     splay(x,rt);splay(y,c[x][1]);
 61     int z=c[y][0];
 62     rev[z]^=1;
 63     return;
 64 }
 65 void build(int l,int r,int f){
 66     if(l>r)return;
 67     int mid=l+r>>1;
 68     int now=a[mid].v,last=a[f].v;
 69     fa[now]=last;c[last][mid>=f]=now;
 70     if(l==r)
 71     {
 72         rev[now]=0;size[now]=1;return;
 73     }
 74     build(l,mid-1,mid);build(mid+1,r,mid);
 75     pushdown(now);
 76     return;
 77 }
 78 int ans[N];
 79 int main()
 80 {
 81     scanf("%d",&n);
 82     rt=(n+3)>>1;mn[0]=1e9;
 83     for(int i=2;i<=n+1;++i)scanf("%d",&a[i].v);
 84     for(int i=1;i<=n;++i)a[i+1].pos=i;
 85     sort(a+2,a+n+2);
 86     for(int i=2;i<=n+1;++i)a[i].v=i;a[1].v=1;a[n+2].v=n+2;
 87     sort(a+2,a+n+2,cmp);
 88     build(1,n+2,0);
 89     rt=a[(n+3)>>1].v;
 90     for(int i=1;i<=n;++i)
 91     {
 92         splay(i+1,rt);
 93         ans[i]=size[c[rt][0]];
 94         rever(i,ans[i]);
 95     }
 96     for(int i=1;i<n;++i)
 97     {
 98         printf("%d ",ans[i]);
 99     }
100     printf("%d",ans[n]);
101     return 0;
102 }

 

转载于:https://www.cnblogs.com/nbwzyzngyl/p/8287925.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值