洛谷4291 [HAOI2008]排名系统

Luogu

BZOJ

分析

这道题有几个操作:

  • 插入
  • 修改
  • 查询第$k$大
  • 查询排名

修改可以视作删除+插入,用平衡树来搞就行了。

要维护分数和时间两个关键字,然后我不会写双关键字的平衡树,所以就用了pb_ds

代码

//It is made by M_sea
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define re register
using namespace std;
using namespace __gnu_pbds;

const int N=500000+10;

struct node {
    int val,id;
    bool operator <(const node& rhs) const {
        if (val!=rhs.val) return val>rhs.val;
        else return id<rhs.id;
    }
};

tree<node,null_type,less<node>,rb_tree_tag,tree_order_statistics_node_update> T;
//BZOJ上请将null_type改为null_mapped_type

map<string,int> id;
string name[N];
int val[N];
int cnt=0,tot=0;

int main() {
    ios::sync_with_stdio(false);
    int n; cin>>n;
    while (n--) {
        char op; string s; cin>>op>>s;
        if (op=='+') {
            if (id[s]) T.erase((node){val[id[s]],id[s]}),--tot;
            cin>>val[++cnt],id[s]=cnt,name[cnt]=s;
            T.insert((node){val[cnt],cnt}),++tot;
        }
        else if (op=='?') {
            if (s[0]>='0'&&s[0]<='9') {
                int x=0,l=s.length();
                for (re int i=0;i<l;++i) x=x*10+s[i]-'0';
                for (re int i=x-1;i<min(tot,x+9);++i)
                    cout<<name[T.find_by_order(i)->id]<<" ";
                cout<<endl;
            }
            else
                cout<<T.order_of_key((node){val[id[s]],id[s]})+1<<endl;
        }
    }
    return 0;
}
最后修改:2019 年 09 月 24 日 10 : 09 PM

发表评论