P4291 [HAOI2008]排名系统

传送门

怎么主要写的都是平衡树,这种查询排名,查询第 $K$ 大的操作直接权值线段树就行了

把读入的数据离散化一波,然后开个 $map$ 维护每个人最后一次插入时在线段树上的位置,直接线段树维护就完事了

查询排名就询问大于它的节点数量,查询第 $K$ 大直接线段树上二分

就是数据格式比较恶心,细节有点多

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<map>
using namespace std;
typedef long long ll;
inline int read()
{
    int x=0,f=1; char ch=getchar();
    while(ch<‘0‘||ch>‘9‘) { if(ch==‘-‘) f=-1; ch=getchar(); }
    while(ch>=‘0‘&&ch<=‘9‘) { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
    return x*f;
}
const int N=5e5+7;
int n;
struct dat{
    int scr,tim; string nam; char opt;
    inline bool operator < (const dat &tmp) const {
        return scr!=tmp.scr ? scr<tmp.scr : tim>tmp.tim;
    }
}c[N],d[N];
map <string,int> pre;
int t[N<<2],pos,v,res;
void add(int o,int l,int r)
{
    t[o]+=v; if(l==r) return;
    int mid=l+r>>1;
    if(pos<=mid) add(o<<1,l,mid);
    else add(o<<1|1,mid+1,r);
}
void query_rnk(int o,int l,int r)
{
    if(l==r) return;
    int mid=l+r>>1;
    if(pos<=mid) query_rnk(o<<1,l,mid),res+=t[o<<1|1];
    else query_rnk(o<<1|1,mid+1,r);
}
void query(int o,int l,int r)
{
    if(l==r) { res=l; return; }
    int mid=l+r>>1;
    if(v>t[o<<1|1]) v-=t[o<<1|1],query(o<<1,l,mid);
    else query(o<<1|1,mid+1,r);
}
inline int Val(string s)
{
    int m=s.size(),res=0;
    for(int i=0;i<m;i++) res=res*10+s[i]-‘0‘;
    return res;
}
int main()
{
    n=read();
    for(int i=1;i<=n;i++)
    {
        cin>>d[i].opt>>d[i].nam;
        if(d[i].opt==‘+‘) d[i].scr=read();
        d[i].tim=i; c[i]=d[i];
    }
    sort(d+1,d+n+1); int tot=0;
    for(int i=1;i<=n;i++)
    {
        if(c[i].opt==‘+‘)
        {
            pos=pre[c[i].nam];
            if(pos) v=-1,add(1,1,n);
            else tot++;
            pos=lower_bound(d+1,d+n+1,c[i])-d;
            v=1; add(1,1,n); pre[c[i].nam]=pos;
            continue;
        }
        if(c[i].nam[0]>‘9‘||c[i].nam[0]<‘0‘)
        {
            res=0; pos=pre[c[i].nam]; query_rnk(1,1,n);
            printf("%d\n",res+1); continue;
        }
        for(int k=1,j=Val(c[i].nam); k<=10&&j<=tot; k++,j++)
        {
            v=j; res=0; query(1,1,n);
            cout<<d[res].nam; printf(" ");
        }
        printf("\n");
    }
    return 0;
}

原文地址:https://www.cnblogs.com/LLTYYC/p/11451819.html

时间: 2024-10-08 22:54:50

P4291 [HAOI2008]排名系统的相关文章

数据结构(Splay平衡树):HAOI2008 排名系统

[HAOI2008] 排名系统 [题目描述] 排名系统通常要应付三种请求:上传一条新的得分记录.查询某个玩家的当前排名以及返回某个区段内的排名记录.当某个玩家上传自己最新的得分记录时,他原有的得分记录会被删除.为了减轻服务器负担,在返回某个区段内的排名记录时,最多返回10条记录. [输入] 第一行是一个整数n(10<=n<=250000)表示请求总数目.接下来n行,每行包含了一个请求.请求的具体格式如下: +Name Score 上传最新得分记录.Name表示玩家名字,由大写英文字母组成,不超

bzoj 1862/1056 [HAOI2008]排名系统

原题链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1862 很恶心的 一道题,我也不晓得自己是第几次写这题了%>_<%. 写了两种方法,平衡树+哈希和平衡树+map.哈希函数是抄别人的.比较了一下还是哈希快一些. 题意很简单,就不说了. 具体思路是,平衡树维护排名,map建立姓名和分数一一对应的关系. 求rank时题意默认是越先提交得分排名越靠前(相同得分的条件下). 具体如下: 平衡树+map 1 #include<algorit

[haoi2008]排名系统

蛤省省选题. 一道彻头彻尾的码农题. 该题的主要知识点有:字符串hash,平衡树.(两颗平衡树?). 4T用splay怎么都调不过.可能是由于splay常数太大.(想写treap,但又实在不想写). 字符串hash不想写啊,用map水的话时限卡着. 这题就当我过了吧... 过不去的程序: #include<iostream> #include<algorithm> #include<cstring> #include<vector> #include<

bzoj1056 [HAOI2008]排名系统【updating】

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1056 [题解] 就是一棵splay..吧? 一种用map,一种用hash表 本地测hash表跑的飞快,甚至比网络上只跑1s的还快,还是T了...qwq 查不出啊(逃 先晾在这吧,坑再说 map版本: # include <map> # include <stdio.h> # include <string.h> # include <iostream>

【pb_ds】bzoj1056 [HAOI2008]排名系统/bzoj1862 [Zjoi2006]GameZ游戏排名系统

STL裸题,线下AC,bzoj无限RE ing…… 1 #include<cstdio> 2 #include<cctype> 3 #include<iostream> 4 #include<string> 5 #include<ext/pb_ds/assoc_container.hpp> 6 #include<ext/pb_ds/tree_policy.hpp> 7 using namespace std; 8 using name

HNOI2008 and ZJOI2006 排名系统

1056: [HAOI2008]排名系统 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1311  Solved: 337[Submit][Status] Description 排名系统通常要应付三种请求:上传一条新的得分记录.查询某个玩家的当前排名以及返回某个区段内的排名记录.当某个玩家上传自己最新的得分记录时,他原有的得分记录会被删除.为了减轻服务器负担,在返回某个区段内的排名记录时,最多返回10条记录. Input 第一行是一个整数n(n

【HAOI2008】排名系统

[题目描述] 排名系统通常要应付三种请求:上传一条新的得分记录.查询某个玩家的当前排名以及返回某个区段内的排名记录.当某个玩家上传自己最新的得分记录时,他原有的得分记录会被删除.为了减轻服务器负担,在返回某个区段内的排名记录时,最多返回10条记录. [输入格式] 第一行是一个整数n(n>=10)表示请求总数目.接下来n行,每行包含了一个请求.请求的具体格式如下: +Name Score 上传最新得分记录.Name表示玩家名字,由大写英文字母组成,不超过10个字符.Score为最多8位的正整数.

BZOJ 1862: [Zjoi2006]GameZ游戏排名系统 Splay

Splay的基本操作,比较繁琐..... 有个一坑点,sorce会超int 1862: [Zjoi2006]GameZ游戏排名系统 Time Limit: 5 Sec  Memory Limit: 64 MB Submit: 913  Solved: 343 [Submit][Status][Discuss] Description GameZ为他们最新推出的游戏开通了一个网站.世界各地的玩家都可以将自己的游戏得分上传到网站上.这样就可以看到自己在世界上的排名.得分越高,排名就越靠前.当两个玩家

BZOJ 1862: [Zjoi2006]GameZ游戏排名系统 [treap hash]

1862: [Zjoi2006]GameZ游戏排名系统 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1318  Solved: 498[Submit][Status][Discuss] Description GameZ为他们最新推出的游戏开通了一个网站.世界各地的玩家都可以将自己的游戏得分上传到网站上.这样就可以看到自己在世界上的排名.得分越高,排名就越靠前.当两个玩家的名次相同时,先上传记录者优先.由于新游戏的火爆,网站服务器已经难堪重负.为此