●Splay的一些题

个人感觉:

  • 代码长;
  • 函数多;
  • (很套路);
  • (很强的Splay,无愧于“区间王”)

NOI2005维修数列

  • 一个可以当模板学习的题,包含了众多操作(函数):
  • 区间插入,删除,更新,翻转,询问信息以及”回收空间”(名字很刚)等。
  • update()pushdown() rotate() splay() build() find() split() insert() rec() erase() query() rever() modify()还有main()
  • 建议初学Splay者打一打;
  • 代码:
  •   1 #include<queue>
      2 #include<cmath>
      3 #include<cstdio>
      4 #include<cstring>
      5 #include<cstdlib>
      6 #include<iostream>
      7 #include<algorithm>
      8 #define inf 1000000000
      9 #define N 1000005
     10 using namespace std;
     11 int read()
     12 {
     13     int x=0,f=1;char ch=getchar();
     14     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     15     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
     16     return x*f;
     17 }
     18 int n,m,rt,cnt,k,len,val; char ch[10];
     19 int a[N],id[N],fa[N],c[N][2];
     20 int sum[N],siz[N],v[N],mx[N],lx[N],rx[N];
     21 bool tag[N],rev[N];
     22 queue<int> q;
     23 void update(int x)                                            
     24 {
     25     int l=c[x][0],r=c[x][1];
     26     sum[x]=sum[l]+sum[r]+v[x];
     27     siz[x]=siz[l]+siz[r]+1;
     28     mx[x]=max(mx[l],mx[r]);
     29     mx[x]=max(mx[x],rx[l]+v[x]+lx[r]);
     30     lx[x]=max(lx[l],sum[l]+v[x]+lx[r]);
     31     rx[x]=max(rx[r],sum[r]+v[x]+rx[l]);
     32 }
     33 void pushdown(int x)                                          
     34 {
     35     int l=c[x][0],r=c[x][1];
     36     if(tag[x])
     37     {
     38         rev[x]=tag[x]=0;                          
     39         if(l) tag[l]=1,v[l]=v[x],sum[l]=v[l]*siz[l];
     40         if(r) tag[r]=1,v[r]=v[x],sum[r]=v[r]*siz[r];
     41         if(v[x]>=0)
     42         {
     43             if(l) lx[l]=rx[l]=mx[l]=sum[l];
     44             if(r) lx[r]=rx[r]=mx[r]=sum[r];
     45         }
     46         else 
     47         {
     48             if(l)lx[l]=rx[l]=0,mx[l]=v[x];
     49             if(r)lx[r]=rx[r]=0,mx[r]=v[x];
     50         }
     51     }
     52     if(rev[x])
     53     {
     54         rev[x]^=1;rev[l]^=1;rev[r]^=1;        
     55          swap(lx[l],rx[l]);swap(lx[r],rx[r]); 
     56         swap(c[l][0],c[l][1]);swap(c[r][0],c[r][1]);
     57     }
     58 }
     59 void rotate(int x,int &k)//Ðýת£¨µ¥£© 
     60 {
     61     int y=fa[x],z=fa[y];
     62     int l=(x!=c[y][0]),r=l^1;
     63     if(y==k) k=x;
     64     else c[z][y!=c[z][0]]=x;
     65     fa[x]=z; fa[y]=x; fa[c[x][r]]=y;
     66     c[y][l]=c[x][r]; c[x][r]=y;
     67     update(y); update(x);
     68 }
     69 void splay(int x,int &k) 
     70 {
     71     int y,z;
     72     while(x!=k)
     73     {
     74         y=fa[x],z=fa[y];
     75         if(y!=k)
     76         {
     77             if(c[y][0]==x^c[z][0]==y) rotate(x,k);
     78             else rotate(y,k);
     79         }
     80         rotate(x,k);
     81     }
     82 }
     83 void build(int l,int r,int f)
     84 {
     85     if(l>r) return;
     86     int mid=l+r>>1,now=id[mid],last=id[f];
     87     if(l==r)
     88     {
     89         sum[now]=a[l];
     90         siz[now]=1;
     91         tag[now]=rev[now]=0;
     92         if(a[l]>=0)lx[now]=rx[now]=mx[now]=a[l];
     93         else lx[now]=rx[now]=0,mx[now]=a[l];
     94     }
     95     build(l,mid-1,mid);build(mid+1,r,mid);
     96     v[now]=a[mid];
     97     fa[now]=last;
     98     c[last][mid>=f]=now;
     99     update(now);
    100 }
    101 int find(int k,int x) 
    102 {
    103     pushdown(k);
    104     if(siz[c[k][0]]+1==x) return k; 
    105     if(siz[c[k][0]]>=x) return find(c[k][0],x);
    106     else return find(c[k][1],x-siz[c[k][0]]-1);
    107 }
    108 int split(int k,int len)
    109 {                                                                                                    
    110     int x=find(rt,k),y=find(rt,k+len+1);
    111     splay(x,rt);splay(y,c[x][1]);
    112     return c[y][0];
    113 }
    114 void insert(int k,int len)
    115 {
    116     for(int i=1;i<=len;i++)
    117     if(!q.empty()) id[i]=q.front(),q.pop();
    118     else id[i]=++cnt;
    119     for(int i=1;i<=len;i++) a[i]=read();
    120     build(1,len,0);
    121     int x=id[1+len>>1];
    122     int z=find(rt,k+1),y=find(rt,k+2);//µÚһλΪ-inf 
    123     splay(z,rt); splay(y,c[z][1]);
    124     fa[x]=y; c[y][0]=x;
    125     update(y);update(fa[y]);
    126 }
    127 void rec(int x) 
    128 {                                                            
    129     if(!x) return;
    130     int l=c[x][0],r=c[x][1];
    131     rec(l); rec(r);
    132     q.push(x);
    133     fa[x]=c[x][0]=c[x][1]=0;
    134     tag[x]=rev[x]=0;
    135 }
    136 void erase(int k,int len)
    137 {
    138     int x=split(k,len),y=fa[x];
    139     rec(x); c[y][0]=0;
    140     update(y);update(fa[y]);
    141 }
    142 void query(int k,int len)
    143 {
    144     int x=split(k,len);
    145     printf("%d\n",sum[x]);
    146 }
    147 void rever(int k,int len)//Çø¼ä·­×ª 
    148 {
    149     int x=split(k,len),y=fa[x];
    150     if(!tag[x])
    151     {
    152         rev[x]^=1;                        
    153         swap(lx[x],rx[x]);
    154         swap(c[x][0],c[x][1]);
    155         update(y);update(fa[y]);
    156     }
    157 }
    158 void modify(int k,int len,int val)
    159 {
    160     int x=split(k,len),y=fa[x];
    161     tag[x]=1; v[x]=val;
    162     sum[x]=v[x]*siz[x];
    163     if(v[x]>=0) lx[x]=rx[x]=mx[x]=sum[x];
    164     else lx[x]=rx[x]=0,mx[x]=v[x];
    165     update(y);update(fa[y]);
    166 }
    167 int main()
    168 {
    169     n=read();m=read();
    170     mx[0]=a[1]=a[n+2]=-inf; id[1]=1; id[n+2]=n+2;
    171     for(int i=2;i<=n+1;i++) a[i]=read(),id[i]=i;
    172     build(1,n+2,0);
    173     rt=n+3>>1; cnt=n+2;
    174     while(m-->0)
    175     {
    176         scanf("%s",ch);
    177         if(ch[0]!='M'||ch[2]!='X') k=read(),len=read();
    178         if(ch[0]=='I') insert(k,len);
    179         if(ch[0]=='D') erase(k,len);
    180         if(ch[0]=='R') rever(k,len);
    181         if(ch[0]=='G') query(k,len);
    182         if(ch[0]=='M')
    183         {
    184             if(ch[2]=='X')printf("%d\n",mx[rt]);
    185             else val=read(),modify(k,len,val);
    186         }
    187     }
    188     return 0;
    189 }
    I'm here!

     

宠物收养所(codves 1285)

  • 用Splay维护一个权值树,每次进行查找,删除或插入操作,较简单。
  • 注意要mod
  • 代码:
  •  1 #include<cstdio>
     2 #include<iostream>
     3 using namespace std;
     4 int rt,size,n,t1,t2,kind;
     5 long long ans;
     6 int fa[80005],tr[80005][2],num[80005];
     7 void rotate(int x,int &k)
     8 {
     9     int y=fa[x],z=fa[y];
    10     int l=(x!=tr[y][0]),r=l^1;
    11     if(y!=k) tr[z][(y!=tr[z][0])]=x;
    12     else k=x;
    13     fa[x]=z;fa[y]=x;fa[tr[x][r]]=y;
    14     tr[y][l]=tr[x][r];tr[x][r]=y;
    15 }
    16 void splay(int x,int &k)
    17 {
    18     int y,z;
    19     while(x!=k)
    20     {
    21         y=fa[x],z=fa[y];
    22         if(y!=k)
    23         {
    24             if((x==tr[y][0])^(y==tr[z][0]))rotate(x,k);
    25             else rotate(y,k);    
    26         }
    27         rotate(x,k);
    28     }
    29 }
    30 void ins(int &k,int x,int last)
    31 {
    32     if(k==0){size++;k=size;num[k]=x;fa[k]=last;splay(k,rt);return;}
    33     if(x<num[k])ins(tr[k][0],x,k);else ins(tr[k][1],x,k);
    34 }
    35 void find_pre(int k,int x)
    36 {
    37     if(k==0) return;
    38     if(num[k]<=x){t1=k;find_pre(tr[k][1],x);}
    39     else find_pre(tr[k][0],x);
    40 }
    41 void find_bac(int k,int x)
    42 {
    43     if(k==0) return;
    44     if(num[k]>=x){t2=k;find_bac(tr[k][0],x);}
    45     else find_bac(tr[k][1],x);
    46 }
    47 void del(int x)
    48 {
    49     splay(x,rt);
    50     if(tr[x][0]*tr[x][1]==0) rt=tr[x][0]+tr[x][1];
    51     else
    52     {
    53         int k=tr[x][1];
    54         while(tr[k][0])k=tr[k][0];
    55         tr[k][0]=tr[x][0];fa[tr[x][0]]=k; 
    56         rt=tr[x][1];
    57     }
    58     fa[rt]=0;
    59 }
    60 int main()
    61 {
    62     scanf("%d",&n);int f,x;
    63     for(int i=1;i<=n;i++)
    64     {
    65         scanf("%d%d",&f,&x);
    66         if(!rt){kind=f;ins(rt,x,0);}
    67         else if(kind==f) ins(rt,x,0);
    68         else
    69         {
    70             t1=t2=-1;
    71             find_pre(rt,x);find_bac(rt,x);
    72             if(t1==-1){ans+=num[t2]-x;ans%=1000000;del(t2);}
    73             else if(t2==-1){ans+=x-num[t1];ans%=1000000;del(t1);}
    74             else
    75             {
    76                 if(num[t2]-x>=x-num[t1]) ans+=x-num[t1],del(t1);// µ± a-b==a+bʱ£¬Ñ¡a-b 
    77                 else ans+=num[t2]-x,del(t2); ans%=1000000;
    78             }
    79             
    80         }
    81         
    82     }
    83     printf("%d",ans);
    84     return 0;
    85 }
    I'm still here!
     1 #include<iostream>
     2 #include<cstdio>
     3 #define MAXN 80005
     4 #define INF 0x3f3f3f3f
     5 using namespace std;
     6 int fa[MAXN],ch[MAXN][2],num[MAXN];
     7 int rk,root,tot,t1,t2;
     8 void rotate(int x,int &k)
     9 {
    10     int y=fa[x],z=fa[y];
    11     int l=ch[y][1]==x,r=1^l;
    12     if(y==k) k=x;
    13     else ch[z][ch[z][1]==y]=x;
    14     fa[ch[x][r]]=y; fa[y]=x; fa[x]=z;
    15     ch[y][l]=ch[x][r]; ch[x][r]=y;
    16 }
    17 void splay(int x,int &k)
    18 {
    19     int y,z;
    20     while(x!=k)
    21     {
    22         y=fa[x]; z=fa[y];
    23         if(y!=k) ((ch[z][0]==y)^(ch[y][0]==x)) ? rotate(x,k):rotate(y,k);
    24         rotate(x,k);
    25     }
    26 }
    27 void insert(int &k,int x,int last)
    28 {
    29     if(!k){k=++tot;fa[k]=last;num[k]=x;splay(k,root);return;}
    30     insert(ch[k][x>=num[k]],x,k);
    31 }
    32 void del(int x)
    33 {
    34     splay(x,root);
    35     if(!(ch[root][0]*ch[root][1])) root=ch[root][0]+ch[root][1];
    36     else
    37     {
    38         int p=ch[root][1];
    39         while(ch[p][0]) p=ch[p][0];
    40         fa[ch[root][0]]=p; ch[p][0]=ch[root][0];
    41         root=ch[root][1];
    42     }
    43     fa[root]=0;
    44 }
    45 void find_fro(int k,int x)
    46 {
    47     if(!k) return;
    48     if(num[k]<=x) t1=k,find_fro(ch[k][1],x);
    49     else find_fro(ch[k][0],x);
    50 }
    51 void find_bac(int k,int x)
    52 {
    53     if(!k) return;
    54     if(num[k]>=x) t2=k,find_bac(ch[k][0],x);
    55     else find_bac(ch[k][1],x);
    56 }
    57 int main()
    58 {
    59     int n,ans=0,k,a,tmp,p; scanf("%d",&n);
    60     while(n--)
    61     {
    62         scanf("%d%d",&k,&a);
    63         if(!root||rk==k) rk=k,insert(root,a,0);
    64         else 
    65         {
    66             t1=INF; t2=INF; tmp=INF; p=0;
    67             find_fro(root,a);
    68             find_bac(root,a);
    69             if(t1!=INF&&tmp>a-num[t1]) p=t1,tmp=a-num[t1];
    70             if(t2!=INF&&tmp>num[t2]-a) p=t2,tmp=num[t2]-a; 
    71             if(p) del(p);
    72             ans=(ans+tmp)%1000000;
    73         }
    74     }
    75     printf("%d",ans);
    76     return 0;
    77 }
    7.27 注意!的优先级大于*(乘号)啊!!!QAQ

     

营业额统计(codevs 1296)

  • 用Splay维护营业额(权值树),每次先查找小于今日营业额的最大值和大于今日营业额的最小值,(也可以有相等的请况),然后取最优解加入ans中,在插入今日营业额;
  • 和上题有点像
  • 但不知我的代码为何在codevs上要TLE一组,在COGS上要WA一组和TLE一组(求助!
  • 代码:
  •  1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<cmath>
     5 #define N 40000
     6 using namespace std;
     7 int fa[N],ch[N][2],num[N];
     8 int n,a,t1,t2,root,sz;
     9 void rotate(int x,int &k)
    10 {   
    11     int y,z,l,r;
    12     z=fa[y=fa[x]];
    13     r=1^(l=(ch[y][1]==x));
    14     if(y==k)k=x;
    15     else ch[z][ch[z][1]==y]=x;
    16     fa[x]=z; fa[y]=x; fa[ch[x][r]]=y;
    17     ch[y][l]=ch[x][r];ch[x][r]=y;
    18 }
    19 void splay(int x,int &k)
    20 {
    21     int y,z;
    22     while(x!=k)
    23     {
    24         z=fa[y=fa[x]];
    25         if(y!=k) ch[z][0]==y^ch[y][0]==x?rotate(x,k):rotate(y,k);
    26         rotate(x,k);
    27     }
    28 }
    29 void insert(int x,int last,int &k)
    30 {
    31     if(!k)
    32     {
    33         k=++sz;
    34         num[sz]=x;
    35         fa[k]=last;
    36         splay(k,root);
    37         return;
    38     }
    39     if(num[k]==x)return;
    40     insert(x,k,ch[k][x>num[k]]);
    41 }
    42 void find_fro(int x,int k)
    43 {
    44     if(!k)return;//¡ñ¡ð¡ð
    45     if(num[k]<=x){t1=k;find_fro(x,ch[k][1]);}
    46     else find_fro(x,ch[k][0]);
    47 }
    48 void find_bac(int x,int k)
    49 {
    50     if(!k)return;
    51     if(num[k]>=x){t2=k;find_bac(x,ch[k][0]);}
    52     else find_bac(x,ch[k][1]);
    53 }
    54 int main()
    55 {
    56     int ans=0;
    57     scanf("%d%d",&n,&ans);
    58     insert(ans,0,root);n--;
    59     while(n--)
    60     {
    61         scanf("%d",&a);
    62         t1=t2=-1; int tmp=0x3f3f3f3f;
    63         find_fro(a,root);
    64         find_bac(a,root);    
    65         if(t1!=-1) tmp=min(tmp,a-num[t1]);
    66         if(t2!=-1) tmp=min(tmp,num[t2]-a);
    67         insert(a,0,root); 
    68         ans+=tmp;                        
    69     }
    70     printf("%d",ans);
    71     return 0;
    72 }
    I'm here,too!

     

●反转卡片(codevs 1743)

  • 一个区间翻转的题,要用到lazy标记,较简单。
  • 代码:
  •  1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<cmath>
     5 #define N 300005
     6 using namespace std;
     7 int n,cnt,rt;
     8 int a[N],c[N][2],fa[N],siz[N],rev[N],num[N];
     9 int read()
    10 {
    11     int x=0,f=1;char ch=getchar();
    12     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    13     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    14     return x*f;
    15 }
    16 void update(int k)
    17 {
    18     siz[k]=siz[c[k][0]]+siz[c[k][1]]+1;
    19 }
    20 void pushdown(int k)
    21 {
    22     if(!rev[k]) return;
    23     int l=c[k][0],r=c[k][1];
    24     rev[l]^=1; rev[r]^=1; rev[k]^=1;
    25     swap(c[l][0],c[l][1]);
    26     swap(c[r][0],c[r][1]);
    27 }
    28 int find(int x,int k)
    29 {
    30     pushdown(k);
    31     if(siz[c[k][0]]+1==x) return k;
    32     else if(siz[c[k][0]]+1>x) return find(x,c[k][0]);
    33     else return find(x-siz[c[k][0]]-1,c[k][1]);
    34 }
    35 void rotate(int x,int &k)
    36 {
    37     int y=fa[x],z=fa[y];
    38     int l=c[y][0]!=x,r=l^1;
    39     if(y==k) k=x;
    40     else c[z][c[z][0]!=y]=x;
    41     fa[x]=z; fa[y]=x; fa[c[x][r]]=y;
    42     c[y][l]=c[x][r]; c[x][r]=y;
    43     update(y); update(x);
    44 }
    45 void splay(int x,int &k)
    46 {
    47     int y,z;
    48     while(x!=k)
    49     {
    50         y=fa[x],z=fa[y];
    51         if(y!=k)
    52         {
    53             if(c[z][0]==y^c[y][0]==x) rotate(x,k);
    54             else rotate(y,k);
    55         }
    56         rotate(x,k);
    57     }
    58 }
    59 int split(int k,int len)
    60 {
    61     int x=find(k,rt),y=find(k+len+1,rt);
    62     splay(x,rt); splay(y,c[x][1]);
    63     return c[y][0];
    64 }
    65 void rever(int k,int len)
    66 {
    67     int x=split(k,len);
    68     rev[x]^=1;
    69     swap(c[x][0],c[x][1]);
    70 }
    71 void build(int l,int r,int f)
    72 {
    73     if(l>r) return;
    74     int mid=l+r>>1;
    75     c[f][mid>=f]=mid; 
    76     fa[mid]=f;
    77     num[mid]=a[mid];
    78     build(l,mid-1,mid);
    79     build(mid+1,r,mid);
    80     update(mid);
    81 }
    82 int main()
    83 {
    84     n=read();
    85     a[1]=a[n+2]=0;
    86     for(int i=2;i<=n+1;i++) a[i]=read();
    87     build(1,n+2,0);
    88     rt=n+3>>1;
    89     int len=num[find(2,rt)];
    90     while(len!=1)
    91     {
    92         cnt++;
    93         rever(1,len);
    94         len=num[find(2,rt)];
    95     }
    96     printf("%d",cnt);
    97     return 0;
    98 }
    I'm here as well!

     

●蚱蜢(codevs 1343)

  • Splay维护蚱蜢的位置和区间最大值;
  • 用到单点删除和插入;
  • (开始题看错了,以为是区间交换,调了半天也没发现代码错误,然后再一看题,……….)
  • 代码:
  •  1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<cmath>
     5 #define N 100050
     6 using namespace std;
     7 int fa[N],c[N][2],a[N],mx[N],siz[N];
     8 int n,m,root;
     9 void pushup(int x)
    10 {
    11     int l=c[x][0],r=c[x][1];
    12     siz[x]=siz[l]+siz[r]+1; mx[x]=max( max(mx[l],mx[r]),a[x]);
    13 }
    14 void rotate(int x,int &k)
    15 {
    16     int y=fa[x],z=fa[y],l=(c[y][0]!=x),r=1^l;
    17     if(y==k) k=x; else c[z][c[z][0]!=y]=x;
    18     fa[x]=z; fa[y]=x; fa[c[x][r]]=y;
    19     c[y][l]=c[x][r]; c[x][r]=y;
    20     pushup(y);pushup(x);
    21 }
    22 void splay(int x,int &k)
    23 {
    24     int y,z;
    25     while(x!=k)
    26     {
    27         y=fa[x]; z=fa[y];
    28         if(y!=k) { if(c[z][0]==y^c[y][0]==x) rotate(x,k); else rotate(y,k); }
    29         rotate(x,k);
    30     }
    31 }
    32 int find(int x,int rt)
    33 {
    34     if(siz[c[rt][0]]+1==x) return rt;
    35     else if(siz[c[rt][0]]+1>x) return find(x,c[rt][0]);
    36     else return find(x-siz[c[rt][0]]-1,c[rt][1]);
    37 }
    38 int split(int a,int b)
    39 {
    40     int x=find(a,root),y=find(b,root);
    41     splay(x,root); splay(y,c[x][1]);
    42     pushup(y); pushup(x);
    43     if(c[y][0]) return c[y][0];
    44     else return y;
    45 }
    46 void build(int l,int r,int last,int &k)
    47 {
    48     if(l>r) return;
    49     k=l+r>>1; fa[k]=last;
    50     if(l==r){mx[k]=a[k]; siz[k]=1;}
    51     build(l,k-1,k,c[k][0]); build(k+1,r,k,c[k][1]); pushup(k);
    52 }
    53 int main()
    54 {
    55     scanf("%d%d",&n,&m);
    56     for(int i=2;i<=n+1;i++) scanf("%d",&a[i]);
    57     build(1,n+2,0,root); int zm,st,x,y,z,w; char di;
    58     while(m--)
    59     {
    60         scanf("%d %c %d",&zm,&di,&st);
    61         if(di=='L') x=split(zm-st,zm+1);
    62         else x=split(zm+1,zm+st+2);
    63         printf("%d\n",mx[x]);
    64         
    65         x=split(zm,zm+2); y=fa[x];
    66         c[y][0]=0; fa[x]=0; pushup(y); pushup(fa[y]);
    67         
    68         if(di=='L') y=split(zm-st,zm-st+1); 
    69         else y=split(zm+st+1-1,zm+st+2-1);        
    70         fa[x]=y; c[y][0]=x; 
    71         siz[x]=1; mx[x]=a[x]; pushup(y); pushup(fa[y]);
    72     }
    73     return 0;
    74 }
    Click me here!

     

●GameZ游戏排名系统(codevs 1985)

  • 我用的是Splay(权值树)+map(stl),题还不错。
  • 单点插入,删除,查询单点信息,查询区间元素;
  • 注意(分数会有重复的)
  • codevs上是过了,但bzoj上显示Presentation_Error(求助!
  • 代码:
  •   1 #include<iostream>
      2 #include<cstdio>
      3 #include<string>
      4 #include<map>
      5 #define N 250050
      6 #define inf 4294967305
      7 #define ll long long
      8 using namespace std;
      9 map<string,ll> mp;
     10 ll n,root,id,sz=2,un,c[N][2],fa[N],cnt;
     11 char s[15];
     12 struct info{
     13     ll sz,co;
     14     char na[15];
     15     void nw(ll val)
     16     {
     17         sz=1; co=val; ll i=1;
     18         while(s[i]) na[i-1]=s[i],i++; na[i-1]=0;
     19     }
     20 }fo[N];
     21 void pushup(ll x)
     22 {
     23     ll l=c[x][0],r=c[x][1];
     24     fo[x].sz=fo[l].sz+fo[r].sz+1;
     25 }
     26 void rotate(ll x,ll &k)
     27 {
     28     ll y=fa[x],z=fa[y],l=(c[y][0]!=x),r=1^l;
     29     if(y==k) k=x; else c[z][c[z][0]!=y]=x;
     30     fa[x]=z; fa[y]=x; fa[c[x][r]]=y;
     31     c[y][l]=c[x][r]; c[x][r]=y;
     32     pushup(y);pushup(x);
     33 }
     34 void splay(ll x,ll &k)
     35 {
     36     ll y,z;
     37     while(x!=k)
     38     {
     39         y=fa[x]; z=fa[y];
     40         if(y!=k) { if(c[z][0]==y^c[y][0]==x) rotate(x,k); else rotate(y,k); }
     41         rotate(x,k);
     42     }
     43 }
     44 void insert(ll val,ll x,ll last,ll &rt)
     45 {
     46     if(!rt){rt=x; fo[x].nw(val); fa[x]=last; splay(x,root); return;}
     47     insert(val,x,rt,c[rt][fo[rt].co<val]);
     48 }
     49 void erase()
     50 {
     51     splay(id,root);
     52     ll t1,tt1=c[id][0],t2,tt2=c[id][1];
     53     while(tt1) t1=tt1,tt1=c[t1][1];
     54     while(tt2) t2=tt2,tt2=c[t2][0];
     55     splay(t1,root);
     56     splay(t2,c[t1][1]);
     57     un=c[t2][0];
     58     fa[un]=0;
     59     c[t2][0]=0;
     60     pushup(t2); 
     61     pushup(t1);
     62 }
     63 void ask_rank()
     64 {
     65     if(cnt) printf("\n");
     66     splay(id,root);
     67     printf("%lld",fo[c[id][1]].sz+1-1);
     68     cnt++;
     69 }
     70 ll make_number()
     71 {
     72     ll tot=0,i=1;
     73     while(s[i]) tot=tot*10+s[i]-'0',i++;
     74     return tot;
     75 }
     76 void print_name(ll rt)
     77 {
     78     if(!rt) return;
     79     print_name(c[rt][1]);
     80     printf("%s ",fo[rt].na);
     81     print_name(c[rt][0]);
     82 }
     83 ll find(ll x,ll rt)
     84 {
     85     if(fo[c[rt][1]].sz+1==x) return rt;
     86     else if(fo[c[rt][1]].sz+1>x) return find(x,c[rt][1]);
     87     else return find(x-fo[c[rt][1]].sz-1,c[rt][0]);
     88 }
     89 void ask_name(ll a)
     90 {
     91     if(cnt) printf("\n");
     92     cnt++;
     93     ll b=min(a+1+10,sz);
     94     ll x=find(b,root),y=find(a,root);
     95     splay(x,root);
     96     splay(y,c[x][1]);
     97     pushup(y); pushup(x);
     98     print_name(c[y][0]);
     99      
    100 }
    101 int main()
    102 {
    103     scanf("%lld",&n); ll a;
    104     insert(inf,1,0,root);                       
    105     insert(-1,2,0,root);
    106     while(n--)
    107     {
    108         scanf("%s",s);
    109         id=mp[s+1];
    110         if(s[0]=='+')
    111         {
    112             scanf("%lld",&a);
    113             if(!id) insert(a,id=mp[s+1]=++sz,0,root);
    114             else
    115             {
    116                 erase();
    117                 insert(a,un,0,root);
    118             }
    119         }else
    120         if('A'<=s[1]&&s[1]<='Z') ask_rank();
    121         else
    122         {
    123             a=make_number();
    124             ask_name(a);
    125         }
    126     }   
    127     return 0;
    128 }
    ......

     

转载于:https://www.cnblogs.com/zj75211/p/6650486.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值