zoukankan      html  css  js  c++  java
  • Codeforces Round #424 (Div. 2) E. Cards Sorting(线段树)

    题目链接:Codeforces Round #424 (Div. 2) E. Cards Sorting

    题意:

    将n个数放进一个队列,每次检查队首,看看是不是队列中最小的数,如果是就扔掉,如果不是就放到队尾。

    这样直到队列为空,为需要操作多少次。

    题解:

    考虑用两个指针模拟,最开始now指针指向第一个数,然后nxt指针指向下一个将要被删除的数。

    然后我们要算出这里需要移动多少步,然后删掉这个数,一直重复操作,直到将全部的数删完。

    nxt指针可以用set来维护,now指针可以用并查集来维护。

    计算now指针到nxt指针需要移动多少步,可以用线段树或者splay来维护。

    线段树版本:

     1 #include<bits/stdc++.h>
     2 #define RT(l,r) (l+r|l!=r)
     3 #define F(i,a,b) for(int i=a;i<=b;++i)
     4 using namespace std;
     5 
     6 const int N=1e6+7;
     7 int n,now,f[N],cnt,x,sum[N*2];
     8 struct node
     9 {
    10     int x,idx;
    11     bool operator <(const node &b)const{return x!=b.x?x<b.x:idx<b.idx;}
    12 };
    13 set<node>st;
    14 set<node>::iterator it;
    15 
    16 int find(int x){return f[x]!=x?f[x]=find(f[x]):x;}
    17 
    18 int getnxt()
    19 {
    20     int X=st.begin()->x;
    21     it=st.lower_bound({X,now});
    22     if(it==st.end()||it->x > X)
    23         it=st.lower_bound({X,1});
    24     int tmp=it->idx;
    25     st.erase(it);
    26     return tmp;
    27 }
    28 
    29 void update(int pos,int v,int l=1,int r=n)
    30 {
    31     int rt=RT(l,r),m=l+r>>1;
    32     if(l==r){sum[rt]+=v;return;}
    33     if(pos<=m)update(pos,v,l,m);
    34     else update(pos,v,m+1,r);
    35     sum[rt]=sum[RT(l,m)]+sum[RT(m+1,r)];
    36 }
    37 
    38 int query(int L,int R,int l=1,int r=n)
    39 {
    40     int rt=RT(l,r),m=l+r>>1,an=0;
    41     if(L<=l&&r<=R)return sum[rt];
    42     if(L<=m)an+=query(L,R,l,m);
    43     if(R>m)an+=query(L,R,m+1,r);
    44     return an;
    45 }
    46 
    47 
    48 int ask(int a,int b)
    49 {
    50     if(a<=b)return query(a,b);
    51     else return query(a,n)+query(1,b);
    52 }
    53 
    54 int main()
    55 {
    56     scanf("%d",&n);
    57     F(i,1,n)
    58     {
    59         scanf("%d",&x),f[i]=i;
    60         st.insert({x,i}),update(i,1);
    61     }
    62     now=1,cnt=1;
    63     long long ans=0;
    64     while(cnt<=n)
    65     {
    66         int nxt=getnxt();
    67         ans+=ask(now,nxt);
    68         if(nxt<n)f[nxt]=nxt+1;else f[nxt]=1;
    69         if(cnt<n)now=find(nxt);
    70         update(nxt,-1);
    71         cnt++;
    72     }
    73     printf("%lld
    ",ans);
    74     return 0;
    75 }
    View Code

    splay版本:

      1 #include<bits/stdc++.h>
      2 #define F(i,a,b) for(int i=a;i<=b;++i)
      3 using namespace std;
      4 const int N=1e6+7;
      5 int _t;
      6 struct Splay_tree
      7 {
      8     int root,q[N];
      9     int key[N],sz[N],f[N],ch[N][2],add[N];
     10     void init(){root=_t=0;}//初始化为一棵空树
     11     inline void nw(int &x,int val,int fa)
     12     {
     13         x=++_t,key[x]=val,f[x]=fa,sz[x]=1;
     14         ch[x][0]=ch[x][1]=0;
     15     }
     16     inline void pd(int x){}
     17     inline void up(int x){sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1;}
     18     void rotate(int x){
     19         int y=f[x],w=ch[y][1]==x;
     20         ch[y][w]=ch[x][w^1];
     21         if(ch[x][w^1])f[ch[x][w^1]]=y;
     22         if(f[y]){
     23             int z=f[y];
     24             if(ch[z][0]==y)ch[z][0]=x;
     25             if(ch[z][1]==y)ch[z][1]=x;
     26         }
     27         f[x]=f[y],ch[x][w^1]=y,f[y]=x,up(y);
     28     }
     29 
     30     void splay(int x,int w){
     31         int s=1,i=x,y;q[1]=x;
     32         while(f[i])q[++s]=i=f[i];
     33         while(s)pd(q[s--]);
     34         while(f[x]!=w){
     35             y=f[x];
     36             if(f[y]!=w){if((ch[f[y]][0]==y)^(ch[y][0]==x))rotate(x);else rotate(y);}
     37             rotate(x);
     38         }
     39         if(!w)root=x;
     40         up(x);
     41     }
     42     void build(int &x,int l,int r,int fa=0)//按照数组下标建树
     43     {
     44         if(l>r)return;
     45         int mid=l+r>>1;
     46         nw(x,mid,fa);
     47         build(ch[x][0],l,mid-1,x);
     48         build(ch[x][1],mid+1,r,x);
     49         up(x);
     50     }
     51     inline int find(int _key) //返回值为key的节点 若无返回0 若有将其转移到根处
     52     {
     53         if(!root)return 0;
     54         int x=root;
     55         for(pd(x);x&&key[x]!=_key;)x=ch[x][key[x]<_key];
     56         if(x)splay(x,0);
     57         return x;
     58     }
     59     inline void Delete(int r)//删除下标为r的节点
     60     {  
     61         splay(r,0);
     62         int pos=sz[ch[r][0]];
     63         splay(kth(pos),0);
     64         splay(kth(pos+2),root);
     65         ch[ch[root][1]][0]=0;  
     66         up(ch[root][1]),up(root);
     67     } 
     68     inline int kth(int k)//获得第k小
     69     {
     70         if(k>sz[root]||k<=0)return 0;
     71         int x=root,tmp;
     72         while(1)
     73         {
     74             pd(x),tmp=sz[ch[x][0]]+1;
     75             if(k==tmp)break;
     76             if(k<tmp)x=ch[x][0];else k-=tmp,x=ch[x][1];
     77         }
     78         return x;
     79     }
     80 }spt;
     81 //--------------------------------
     82 
     83 int n,now,f[N],ed;
     84 struct node
     85 {
     86     int x,idx;
     87     bool operator <(const node &b)const{return x!=b.x?x<b.x:idx<b.idx;}
     88 }a[N];
     89 set<node>st;
     90 set<node>::iterator it;
     91 int find(int x){return f[x]!=x?f[x]=find(f[x]):x;}
     92 
     93 int getkth(int x)
     94 {
     95     int rt=spt.find(x);
     96     return spt.sz[spt.ch[rt][0]]+1;
     97 }
     98 
     99 int del()
    100 {
    101     it=st.lower_bound({a[ed].x,now});
    102     if(it==st.end()||it->x > a[ed].x)
    103     {
    104         it=st.lower_bound({a[ed].x,1});
    105     }
    106     int tmp=it->idx;
    107     st.erase(it);
    108     return tmp;
    109 }
    110 
    111 int main()
    112 {
    113     scanf("%d",&n);
    114     F(i,1,n)scanf("%d",&a[i].x),a[i].idx=i,f[i]=i,st.insert(a[i]);
    115     sort(a+1,a+1+n);
    116     spt.build(spt.root,1,n+2);
    117     now=1,ed=1;
    118     long long ans=0;
    119     while(ed<=n)
    120     {
    121         int cur=getkth(now+1),tp=del();
    122         int tmp=getkth(tp+1);
    123         if(tmp>=cur)ans+=tmp-cur+1;
    124         else ans+=spt.sz[spt.root]-cur+tmp-1;
    125         int rt=spt.find(tp+1);
    126         spt.Delete(rt);
    127         if(tp<n)f[tp]=tp+1;
    128         else f[tp]=1;
    129         if(ed<n)now=find(f[tp]);
    130         ed++;
    131     }
    132     printf("%lld
    ",ans);
    133     return 0;
    134 }
    View Code
  • 相关阅读:
    与灵感之源的vb.net对应的SmartExcel的C#版本
    winform下提高control在UI中的响应速度
    做了一个petoolkit的gui版本,放几张图上来。
    Reflection中对于out类型的获取
    对企业管理软件“代码后”问题的思考
    看了dannyr的java中文类,自己写了一个。
    所有的WMI可以使用的class
    庆祝浪潮集团成为微软在中国的第四家全球战略合作伙伴!(暂时放首页两天)
    一种系统间集成的同步事务异常处理方法和装置
    一种实现多线并行拣选的方法
  • 原文地址:https://www.cnblogs.com/bin-gege/p/7182608.html
Copyright © 2011-2022 走看看