• BZOJ4415:[SHOI2013]发牌(线段树)


    Description

    假设一开始,荷官拿出了一副新牌,这副牌有N张不同的牌,编号依次为1到N。由于是新牌,所以牌是按照顺序排好的,从牌库顶开始,依次为1, 2,……直到N,N号牌在牌库底。为了发完所有的牌,荷官会进行N次发牌操作,在第i次发牌之前,他会连续进行R_i次销牌操作,R_i由输入给定。请问最后玩家拿到这副牌的顺序是什么样的?

    举个例子,假设N = 4,则一开始的时候,牌库中牌的构成顺序为{1, 2, 3, 4}。

    假设R1=2,则荷官应该连销两次牌,将1和2放入牌库底,再将3发给玩家。目前牌库中的牌顺序为{4, 1, 2}。

    假设R2=0,荷官不需要销牌,直接将4发给玩家,目前牌库中的牌顺序为{1,2}。

    假设R3=3,则荷官依次销去了1, 2, 1,再将2发给了玩家。目前牌库仅剩下一张牌1。

    假设R4=2,荷官在重复销去两次1之后,还是将1发给了玩家,这是因为1是牌库中唯一的一张牌。

    Input

    第1行,一个整数N,表示牌的数量。第2行到第N + 1行,在第i + 1行,有一个整数R_i, 0≤R_i<N

    Output

    第1行到第N行:第i行只有一个整数,表示玩家收到的第i张牌的编号。

    Sample Input

    4
    2
    0
    3
    2

    Sample Output

    3
    4
    2
    1

    HINT

    N<=70万

    Solution

    一看是splay裸题就上splay硬艹结果因为人傻常数大只有80……于是换了线段树写法

    开个线段树存一下每种牌的数量0/1
    在值域线段树上二分即可。
    代码简单易懂

    最后面贴一下我GG的splay

    Code

     1 #include<iostream>
     2 #include<cstdio>
     3 #define N  (700000+1000)
     4 using namespace std;
     5 
     6 int Segt[N<<2];
     7 
     8 inline int read()
     9 {
    10     int x=0,w=1; char c=getchar();
    11     while (!isdigit(c)&&c!='-') c=getchar();
    12     if (c=='-') c=getchar(),w=-1;
    13     while (isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
    14     return x*w;
    15 }
    16 
    17 void Build(int now,int l,int r)
    18 {
    19     if (l==r){Segt[now]=1; return;}
    20     int mid=(l+r)>>1;
    21     Build(now<<1,l,mid); Build(now<<1|1,mid+1,r);
    22     Segt[now]=Segt[now<<1]+Segt[now<<1|1];
    23 }
    24 
    25 void Update(int now,int l,int r,int k)
    26 {
    27     Segt[now]--;
    28     if (l==r){printf("%d
    ",l); return;}
    29     int mid=(l+r)>>1;
    30     if (k<=Segt[now<<1]) Update(now<<1,l,mid,k);
    31     else Update(now<<1|1,mid+1,r,k-Segt[now<<1]);
    32 }
    33 
    34 int main()
    35 {
    36     int n,x,p=0;
    37     n=read();
    38     Build(1,1,n);
    39     for (int i=1; i<=n; ++i)
    40     {
    41         x=read();
    42         p=(p+x)%(n-i+1);
    43         Update(1,1,n,p+1);
    44     }
    45 }
     1 #include<iostream>
     2 #include<cstdio>
     3 #define N (700000+1000)
     4 using namespace std;
     5 
     6 int n,x,Root,Father[N],Son[N][2],Size[N];
     7 
     8 void Update(int x){Size[x]=1+Size[Son[x][0]]+Size[Son[x][1]];}
     9 int Get(int x){return Son[Father[x]][1]==x;}
    10 
    11 inline int read()
    12 {
    13     int x=0,w=1;
    14     char c=getchar();
    15     while (!isdigit(c)&&c!='-') c=getchar();
    16     if (c=='-') c=getchar(),w=-1;
    17     while (isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
    18     return x*w;
    19 }
    20 
    21 void Build(int fa,int l,int r)
    22 {
    23     if (l>r) return;
    24     if (l==r) Size[l]=1;
    25     int mid=(l+r)>>1;
    26     Build(mid,l,mid-1);
    27     Build(mid,mid+1,r);
    28     Father[mid]=fa; Son[fa][mid>fa]=mid;
    29     Update(mid);
    30 }
    31 
    32 void Rotate(int x)
    33 {
    34     int wh=Get(x);
    35     int fa=Father[x],fafa=Father[fa];
    36     if (fafa) Son[fafa][Son[fafa][1]==fa]=x;
    37     Father[fa]=x; Son[fa][wh]=Son[x][wh^1];
    38     Father[x]=fafa; Son[x][wh^1]=fa;
    39     if (Son[fa][wh]) Father[Son[fa][wh]]=fa;
    40     Update(fa); Update(x);
    41 }
    42 
    43 void Splay(int x,int tar)
    44 {
    45     for (int fa; (fa=Father[x])!=tar; Rotate(x))
    46         if (Father[fa]!=tar)
    47             Rotate(Get(fa)==Get(x)?fa:x);
    48     if (!tar) Root=x;
    49 }
    50 
    51 int Findkth(int x)
    52 {
    53     int now=Root;
    54     while (1)
    55         if (Size[Son[now][0]]>=x) now=Son[now][0];
    56         else
    57         {
    58             x-=Size[Son[now][0]];
    59             if (x==1){/*Splay(now,0);*/ return now;}
    60             x--; now=Son[now][1];
    61         }
    62 }
    63 
    64 int Split(int l,int r)
    65 {
    66     int x=Findkth(l);
    67     int y=Findkth(r+2);
    68     Splay(x,0); Splay(y,x);
    69     return Son[y][0];
    70 }
    71 
    72 int main()
    73 {
    74     n=read();
    75     Build(0,1,n+2);
    76     Root=(n+3)>>1;
    77     for (int i=1; i<=n; ++i)
    78     {
    79         x=read();
    80         x%=n-i+1;
    81         if (x)
    82         {
    83             int now=Split(1,x);
    84             Son[Father[now]][Son[Father[now]][1]==now]=0;
    85             Father[now]=0;
    86             int fa=Split(n-i+1-x,n-i+1-x);
    87             Son[fa][1]=now; Father[now]=fa;
    88             Splay(now,0);
    89         }
    90         int now=Split(1,1); printf("%d
    ",now-1);
    91         Son[Father[now]][0]=0;
    92         Father[now]=0; Update(Son[Root][1]);
    93     }
    94 }
  • 相关阅读:
    正则表达式点滴
    异步处理与界面交互
    关于利用VS2008创建项目遇到的小困惑备忘
    using App.cofig to Store value
    Castle ActiveRecord学习笔记三:初始化配置
    无服务器端的UDP群聊功能剖析
    为VS2010默认模板添加版权信息
    理论有何用?不问“何用”,先问“用否”!
    微软没有公开的游标分页
    那些满脑子只考虑后台数据库的人他整天研究的就是针对自己查询一些数据的sql语句
  • 原文地址:https://www.cnblogs.com/refun/p/9236055.html
Copyright © 2020-2023  润新知