• 1056/1862. [ZJOI2006]GameZ游戏排名系统【平衡树-splay】


    Description

    GameZ为他们最新推出的游戏开通了一个网站。世界各地的玩家都可以将自己的游戏得分上传到网站上。这样就可以看到自己在世界上的排名。得分越高,排名就越靠前。当两个玩家的名次相同时,先上传记录者优先。由于新游戏的火爆,网站服务器已经难堪重负。为此GameZ雇用了你来帮他们重新开发一套新的核心。排名系统通常要应付三种请求:上传一条新的得分记录、查询某个玩家的当前排名以及返回某个区段内的排名记录。当某个玩家上传自己最新的得分记录时,他原有的得分记录会被删除。为了减轻服务器负担,在返回某个区段内的排名记录时,最多返回10条记录。

    Input

    第一行是一个整数n(n>=10)表示请求总数目。接下来n行每行包含了一个请求。请求的具体格式如下: +Name Score 上传最新得分记录。Name表示玩家名字,由大写英文字母组成,不超过10个字符。Score为最多8位的正整数。 ?Name 查询玩家排名。该玩家的得分记录必定已经在前面上传。 ?Index 返回自第Index名开始的最多10名玩家名字。Index必定合法,即不小于1,也不大于当前有记录的玩家总数。输入文件总大小不超过2M。 NOTE:用C++的fstream读大规模数据的效率较低

    Output

    对于每条查询请求,输出相应结果。对于?Name格式的请求,应输出一个整数表示该玩家当前的排名。对于?Index格式的请求,应在一行中依次输出从第Index名开始的最多10名玩家姓名,用一个空格分隔。

    Sample Input

    20
    +ADAM 1000000 加入ADAM的得分记录
    +BOB 1000000 加入BOB的得分记录
    +TOM 2000000 加入TOM的得分记录
    +CATHY 10000000 加入CATHY的得分记录
    ?TOM 输出TOM目前排名
    ?1 目前有记录的玩家总数为4,因此应输出第1名到第4名。
    +DAM 100000 加入DAM的得分记录
    +BOB 1200000 更新BOB的得分记录
    +ADAM 900000 更新ADAM的得分记录(即使比原来的差)
    +FRANK 12340000 加入FRANK的得分记录
    +LEO 9000000 加入LEO的得分记录
    +KAINE 9000000 加入KAINE的得分记录
    +GRACE 8000000 加入GRACE的得分记录
    +WALT 9000000 加入WALT的得分记录
    +SANDY 8000000 加入SANDY的得分记录
    +MICK 9000000 加入MICK的得分记录
    +JACK 7320000 加入JACK的得分记录
    ?2 目前有记录的玩家总数为12,因此应输出第2名到第11名。
    ?5 输出第5名到第13名。
    ?KAINE 输出KAINE的排名

    Sample Output

    2
    CATHY TOM ADAM BOB
    CATHY LEO KAINE WALT MICK GRACE SANDY JACK TOM BOB
    WALT MICK GRACE SANDY JACK TOM BOB ADAM DAM

    cnmd辣鸡题目范围都不给清楚?
    调了一上午心态爆炸
    其实只要把树稍微修改一下,原本是左子树是小于的数
    这个题弄成左子树是小于等于的数
    唯一把find函数和其他函数包含Cnt数组部分稍作修改即可。

      1 #include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 #include<map>
      5 #define MAXN (1000000+10)
      6 #define LL long long
      7 using namespace std;
      8 LL Father[MAXN];
      9 LL Son[MAXN][2];
     10 LL Key[MAXN];
     11 LL Size[MAXN];
     12 LL Root,sz;
     13 map<string,LL>Num;
     14 map<LL,string>Name;
     15 LL n;
     16 char c[101];
     17 
     18 inline void Clear(LL x)
     19 {
     20     Father[x]=Son[x][0]=Son[x][1]=Key[x]=Size[x]=0;
     21 }
     22 
     23 inline LL Get(LL x)
     24 {
     25     return Son[Father[x]][1]==x;
     26 }
     27 
     28 inline void Update(LL x)
     29 {
     30     Size[x]=1+Size[Son[x][0]]+Size[Son[x][1]];
     31 }
     32 
     33 inline void Rotate(LL x)
     34 {
     35     LL wh=Get(x);
     36     LL fa=Father[x],fafa=Father[fa];
     37     Son[fa][wh]=Son[x][wh^1];//fa
     38     Father[fa]=x;
     39     if (Son[fa][wh]) Father[Son[fa][wh]]=fa;
     40     Son[x][wh^1]=fa;//x
     41     Father[x]=fafa;
     42     if (fafa) Son[fafa][Son[fafa][1]==fa]=x;//fafa
     43     Update(fa);
     44     Update(x);
     45 }
     46 
     47 inline void Splay(LL x)
     48 {
     49     for (LL fa; fa=Father[x]; Rotate(x))
     50         if (Father[fa])
     51             Rotate(Get(fa)==Get(x)?fa:x);
     52     Root=x;
     53 }
     54 
     55 inline LL Pre()
     56 {
     57     LL now=Son[Root][0];
     58     while (Son[now][1])
     59         now=Son[now][1];
     60     return now;
     61 }
     62 
     63 inline void Insert(LL x)
     64 {
     65     if (!Root)
     66     {
     67         Key[++sz]=x;
     68         Root=sz;
     69         Size[sz]=1;
     70         return;
     71     }
     72     LL fa=0,now=Root;
     73     while (1)
     74     {
     75         fa=now;
     76         now=Son[now][x>Key[now]];
     77         if (!now)
     78         {
     79             Key[++sz]=x;
     80             Father[sz]=fa;
     81             Size[sz]=1;
     82             Son[fa][x>Key[fa]]=sz;
     83             Update(fa);
     84             Splay(sz);
     85             break;
     86         }
     87     }
     88 }
     89 inline LL Find(LL x)
     90 {
     91     LL Ans=0,now=Root;
     92     while (1)
     93         if (Key[x]<Key[now] || Key[x]==Key[now] && x>now)
     94             //这里稍作修改,因为当数相等时肯定后面加入的更小,所以节点的编号可以看作第二关键字
     95             now=Son[now][0];
     96         else
     97         {
     98             Ans+=Size[Son[now][0]];
     99             if (x==now)
    100             {
    101                 Splay(now);
    102                 return Ans+1;
    103             }
    104             Ans++;
    105             now=Son[now][1];
    106         }
    107 }
    108 
    109 inline LL Findx(LL x)
    110 {
    111     LL now=Root;
    112     while (1)
    113         if (x<=Size[Son[now][0]])
    114             now=Son[now][0];
    115         else
    116         {
    117             x-=Size[Son[now][0]];
    118             if (x==1)
    119             {
    120                 Splay(now);
    121                 return now;
    122             }
    123             x--;
    124             now=Son[now][1];
    125         }
    126 }
    127 
    128 inline void Delete(LL x)
    129 {
    130     Splay(x);
    131     if (!Son[Root][0] && !Son[Root][1])
    132     {
    133         Clear(Root);
    134         Root=0;
    135         return;
    136     }
    137     if (!Son[x][0])
    138     {
    139         Root=Son[Root][1];
    140         Clear(Father[Root]);
    141         Father[Root]=0;
    142         return;
    143     }
    144     if (!Son[x][1])
    145     {
    146         Root=Son[Root][0];
    147         Clear(Father[Root]);
    148         Father[Root]=0;
    149         return;
    150     }
    151     LL Oldroot=Root;
    152     LL pre=Pre();
    153     Splay(pre);
    154     Son[Root][1]=Son[Oldroot][1];
    155     Father[Son[Root][1]]=Root;
    156     Clear(Oldroot);
    157     Update(Root);
    158 }
    159 
    160 void Work1()//+
    161 {
    162     LL s;
    163     string st="";
    164     for (LL i=1; i<=strlen(c)-1; ++i)
    165         st+=c[i];
    166     if (Num[st]) Delete(Num[st]);
    167     scanf("%lld",&s);
    168     Insert(s);
    169     Name[Root]=st;
    170     Num[st]=Root;
    171 }
    172 
    173 void Work2()
    174 {
    175     LL s=0;
    176     string st="";
    177     for (LL i=1; i<=strlen(c)-1; ++i)
    178     {
    179         if (c[i]>='A' && c[i]<='Z')
    180             st+=c[i];
    181         if (c[i]>='0' && c[i]<='9')
    182             s=s*10+c[i]-48;
    183     }
    184     if (st!="")
    185         printf("%lld",Size[Root]-Find(Num[st])+1);
    186     if (s)
    187     {
    188         LL i=Size[Root]-s+1,sum=1;
    189         cout<<Name[Findx(i)];
    190         i--;
    191         while (i>=1)
    192         {
    193             cout<<' '<<Name[Findx(i)];
    194             i--;
    195             sum++;
    196             if (sum==10) break;
    197         }
    198 
    199     }
    200     printf("
    ");
    201 }
    202 
    203 int main()
    204 {
    205     scanf("%lld",&n);
    206     for (LL i=1; i<=n; ++i)
    207     {
    208         scanf("%s",&c);
    209         if (c[0]=='+')
    210             Work1();
    211         else
    212             Work2();
    213     }
    214 }
  • 相关阅读:
    关于APP接口设计
    http协议详解-摘抄
    lnmp启动脚本
    MySQL数据库优化总结
    91、sendToTarget与sendMessage
    90、 Android UI模板设计
    Android Intent Action大汇总(转载)
    89、Android EditText 悬浮停靠
    88、android 插件开发教程(转载)
    Android Studio实用插件使用
  • 原文地址:https://www.cnblogs.com/refun/p/8680809.html
Copyright © 2020-2023  润新知