• [bzoj1056] [HAOI2008]排名系统


    Description

      排名系统通常要应付三种请求:上传一条新的得分记录、查询某个玩家的当前排名以及返回某个区段内的排名记录。当某个玩家上传自己最新的得分记录时,他原有的得分记录会被删除。为了减轻服务器负担,在返回某个区段内的排名记录时,最多返回10条记录。

    Input

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

    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
    4
    

    Solution

    平衡树模板题。。

    因为我太懒了字符串哈希直接(map)就好了。

    #include<bits/stdc++.h>
    using namespace std;
    
    #define int long long 
    
    void read(int &x) {
        x=0;int f=1;char ch=getchar();
        for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
        for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
    }
     
    void print(int x) {
        if(x<0) putchar('-'),x=-x;
        if(!x) return ;print(x/10),putchar(x%10+48);
    }
    void write(int x) {if(!x) putchar('0');else print(x);putchar('
    ');}
    
    const int maxn = 5e5+10;
    const int base = 29;
    const int inf = 1e18;
    
    char s[20];
    int tot=2;
    map<string,int > mp;
    
    int hs() {
    	int r=strlen(s+1);string ss="";
    	for(int i=1;i<=r;i++) ss+=s[i];
    	return mp[ss]?mp[ss]:mp[ss]=++tot;
    }
    
    char name[maxn][12];
    int cnt,fa[maxn],son[maxn][2],sz[maxn],val[maxn],rt,vis[maxn],n;
    
    void update(int x) {sz[x]=sz[son[x][0]]+sz[son[x][1]]+1;}
    
    int which(int x) {return son[fa[x]][1]==x;}
    
    void rotate(int x,int &aim) {
    	int y=fa[x],z=fa[y],ww=which(x);
    	if(y==aim) aim=x;
    	else son[z][son[z][1]==y]=x;
    	fa[x]=z,fa[y]=x,fa[son[x][ww^1]]=y;
    	son[y][ww]=son[x][ww^1],son[x][ww^1]=y;
    	update(y),update(x);
    }
    
    void splay(int x,int &aim) {
    	while(x!=aim) {
    		int y=fa[x],z=fa[y];
    		if(y!=aim) rotate(((son[y][1]==x)^(son[z][1]==y))?x:y,aim);
    		rotate(x,aim);
    	}
    }
    
    void insert(int &p,int x,int f) {
    	if(!p) {fa[x]=f,sz[x]=1,p=x;splay(x,rt);return ;}
    	if(val[x]>val[p]) insert(son[p][1],x,p);
    	else insert(son[p][0],x,p);
    }
    
    void del(int x) {
    	splay(x,rt);int pre=son[x][0],nxt=son[x][1];
    	while(son[pre][1]) pre=son[pre][1];
    	while(son[nxt][0]) nxt=son[nxt][0];
    	splay(pre,rt),splay(nxt,son[rt][1]);
    	son[nxt][0]=fa[x]=0;update(nxt),update(pre);
    }
    
    int get_rk(int x) {splay(x,rt);return sz[son[x][1]];}
    
    void dfs(int x) {
    	if(son[x][1]) dfs(son[x][1]);
    	printf("%s ",name[vis[x]]+1);
    	if(son[x][0]) dfs(son[x][0]);
    }
    
    int find(int x,int k) {
    	if(sz[son[x][0]]>=k) return find(son[x][0],k);
    	else if(sz[son[x][0]]+1==k) return x;
    	else return find(son[x][1],k-sz[son[x][0]]-1);
    }
    
    void solve(int l,int r) {
    	splay(find(rt,l-1),rt),splay(find(rt,r+1),son[rt][1]);
    	dfs(son[son[rt][1]][0]);
    }
    
    signed main() {
    	int m;read(m);
    	val[1]=-inf;insert(rt,1,0);
    	val[maxn-1]=inf;insert(rt,maxn-1,0);
    	for(int cas=1;cas<=m;cas++) {
    		memset(s,0,sizeof s);
    		char c=getchar();
    		while(c=='
    '||c==' ') c=getchar();
    		if(c=='+') {
    			scanf("%s",s+1);int x,v,r=strlen(s+1);read(v);s[r+1]=0;
    			if(vis[x=hs()]) del(x);val[x]=v;insert(rt,x,0);
    			if(!vis[x]) {vis[x]=++cnt;n++;for(int i=1;i<=r;i++) name[cnt][i]=s[i];}
    		} else {
    			c=getchar();int top=0;
    			while(c!='
    '&&c!=' '&&c!=EOF) s[++top]=c,c=getchar();
    			if(isdigit(s[1])) {
    				int x=0;
    				for(int i=1;i<=top;i++) x=x*10+s[i]-'0';
    				solve(n-min(n,x+9)+2,n-x+2);puts("");
    			} else write(get_rk(hs()));
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    C# 单例模式
    [C# 线程处理系列]专题四:线程同步
    C#实现远程开机(局域网测试通过)
    C#实现类只实例化一次(被多个类访问调用)
    c#委托与事件、消息、WndProc用法(转)
    UML 类图常用表示方法.
    C# Socket 接受数据不全的处理
    执行数据库操作失败: 连接未关闭。 连接的当前状态为打开
    hdu 2018 母牛的故事 动态规划入门题
    Codeforces 1029B. Creating the Contest 动态规划O(nlogn)解法 及 单调队列O(n)解法
  • 原文地址:https://www.cnblogs.com/hbyer/p/10394681.html
Copyright © 2020-2023  润新知