http://www.lydsy.com/JudgeOnline/problem.php?id=1862

http://www.lydsy.com/JudgeOnline/problem.php?id=1056

这两题一模一样啊。。。。

首先这是一道十分恶心的数据结构题。

一定要注意:

首先平衡树内关键字是重复的,那么我们需要用第二关键字来确认位置,即插入时间。

那么就一定要弄清楚顺序。

!!!

因为这个插入顺序和排名有关

所以插入顺序一定要遵循堆的性质

在本题里,插入顺序是左小右大,和平衡树一样。

还有,本题的size是不论key是否相同的。因为有一定的序,所以答案就一定。

本题我用map来索引名字,来找到它的信息,从而在平衡树里删去。

treap有很多细节,我就不说了,在以前的博文里说过。

那么这题就是码农题了。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <iostream>
#include <algorithm>
#include <map>
#include <string>
using namespace std;
#define rep(i, n) for(int i=0; i<(n); ++i)
#define for1(i,a,n) for(int i=(a);i<=(n);++i)
#define for2(i,a,n) for(int i=(a);i<(n);++i)
#define for3(i,a,n) for(int i=(a);i>=(n);--i)
#define for4(i,a,n) for(int i=(a);i>(n);--i)
#define CC(i,a) memset(i,a,sizeof(i))
#define read(a) a=getint()
#define print(a) printf("%d", a)
#define dbg(x) cout << #x << " = " << x << endl
#define printarr(a, n, m) rep(aaa, n) { rep(bbb, m) cout << a[aaa][bbb]; cout << endl; }
inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; }
inline const int max(const int &a, const int &b) { return a>b?a:b; }
inline const int min(const int &a, const int &b) { return a<b?a:b; }
const int N=250020, oo=~0u>>1;
map<string, pair<int, int> > rk;
int cnt=0, tot=0;
string nam; struct node* null;
struct node {
int key, id;
string name;
int size, wei;
node* ch[2];
node(int _k=0, int _id=0, string _n="", int _s=1) : key(_k), id(_id), name(_n), size(_s) {
ch[0]=ch[1]=null; wei=rand();
}
inline void pushup() { size=ch[0]->size+ch[1]->size+1; }
}*root;
inline void rot(node* &r, const bool d) {
node* t=r->ch[!d]; r->ch[!d]=t->ch[d]; t->ch[d]=r;
r->pushup(); t->pushup();
if(root==r) root=t;
r=t;
}
inline void insert(node* &r, const int &key, const int &id) {
if(r==null) { r=new node(key, id, nam); return; }
bool d=key>r->key;
insert(r->ch[d], key, id);
if(r->ch[d]->wei < r->wei) rot(r, !d);
else r->pushup();
}
inline void del(node* &r, const int &key, const int &id) {
if(r==null) return;
bool d=key>r->key;
if(key==r->key) {
if(id==r->id) {
d=r->ch[0]->wei > r->ch[1]->wei;
if(r->ch[d]==null) {
delete(r);
r=null;
return;
}
rot(r, !d);
del(r->ch[!d], key, id);
}
else del(r->ch[id<r->id], key, id);
}
else del(r->ch[d], key, id);
r->pushup();
}
int getrank(node* r, const int &key, const int &id) {
if(r==null) return 0;
if(key==r->key) {
if(id>r->id) return r->ch[1]->size+getrank(r->ch[0], key, id)+1;
else if(id<r->id) return getrank(r->ch[1], key, id);
else return r->ch[1]->size+1;
}
if(key>r->key) return getrank(r->ch[1], key, id);
else return getrank(r->ch[0], key, id)+r->ch[1]->size+1;
}
node* select(node* r, const int k) {
if(r==null) return null;
int s=r->ch[1]->size+1;
if(s==k) return r;
if(s>k) return select(r->ch[1], k);
else return select(r->ch[0], k-s);
}
void ins(char *nm) {
int key;
string str(nm+1);
read(key);
if(rk.count(str)!=0) {
del(root, rk[str].second, rk[str].first);
rk.erase(str);
--tot;
}
++cnt; ++tot;
rk[str]=pair<int, int> (cnt, key);
nam=str;
insert(root, key, cnt);
}
void ask1(char *nm) {
string str(nm+1);
printf("%d\n", getrank(root, rk[str].second, rk[str].first));
}
void ask2(char *nm) {
int num=0;
string str(nm+1);
for(int i=0; i<str.size(); ++i) num=num*10+str[i]-'0';
int t=min(tot-num+1, 10);
for(int i=0; i<t; ++i) {
printf("%s", select(root, num+i)->name.c_str());
if(i!=t-1) printf(" ");
}
puts("");
}
inline void init() {
null=new node(0, 0, "", 0); null->ch[0]=null->ch[1]=null; null->wei=oo;
root=null;
}
int main() {
init();
int n=getint();
char str[30];
while(n--) {
scanf("%s", str);
if(str[0]=='+') ins(str);
else {
if(str[1]>='A'&&str[1]<='Z') ask1(str);
else ask2(str);
}
}
return 0;
}

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

HINT

20%数据满足N<=100 100%数据满足N<=250000

Source

【BZOJ】1862: [Zjoi2006]GameZ游戏排名系统 & 1056: [HAOI2008]排名系统(treap+非常小心)的更多相关文章

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

    1862: [Zjoi2006]GameZ游戏排名系统 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1318  Solved: 498[Submit][ ...

  2. bzoj 1862: [Zjoi2006]GameZ游戏排名系统 & bzoj 1056: [HAOI2008]排名系统

    傻叉了一晚上,把t打成x,然后这题神奇在于输出一段数,不足的不用输出,一开始我的是直接找没有后面就退,然后这样会格式错误囧……然后最后zj的还卡了下空间,于是不用string就过了……string毁一 ...

  3. bzoj 1056 [HAOI2008]排名系统(1862 [Zjoi2006]GameZ游戏排名系统)

    1056: [HAOI2008]排名系统 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1854  Solved: 502[Submit][Statu ...

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

    Description GameZ为他们最新推出的游戏开通了一个网站.世界各地的玩家都可以将自己的游戏得分上传到网站上.这样就可以看到自己在世界上的排名.得分越高,排名就越靠前.当两个玩家的名次相同时 ...

  5. bzoj1056: [HAOI2008]排名系统 && 1862: [Zjoi2006]GameZ游戏排名系统

    hash 加上 平衡树(名次树). 这道题麻烦的地方就在于输入的是一个名字,所以需要hash. 这个hash用的是向后探查避免冲突,如果用类似前向星的方式避免冲突,比较难写,容易挂掉,但也速度快些. ...

  6. bzoj1056/1862 [Zjoi2006]GameZ游戏排名系统

    题目链接:1,2 treap恶心题,不多说 #include<algorithm> #include<iostream> #include<cstdlib> #in ...

  7. BZOJ_1862_[Zjoi2006]GameZ游戏排名系统&&BZOJ_1056_[HAOI2008]排名系统_Splay

    BZOJ_1862_[Zjoi2006]GameZ游戏排名系统&&BZOJ_1056_[HAOI2008]排名系统_Splay Description 排名系统通常要应付三种请求:上传 ...

  8. [HAOI2008]排名系统& [Zjoi2006]GameZ游戏排名系统

    1056: [HAOI2008]排名系统 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2487  Solved: 711[Submit][Statu ...

  9. [洛谷P2584][ZJOI2006]GameZ游戏排名系统

    题目大意:同[洛谷P4291][HAOI2008]排名系统(双倍经验) 题解:略 卡点:无 C++ Code: #include <cstdio> #include <map> ...

随机推荐

  1. php如何将数组保存为文件的方法? 三个方法让你快速把数组保存成为文件存储

    php 缓存数组形式的变量,实际上就是将 php 将数组写入到一个文本文件或者后缀名为 .php 存储起来,使用的时候直接调用这个文件.那么如何使用 php 将数组保存为文本格式的文件呢?下面分享三种 ...

  2. 开发Web Service的几种方式

    本文作者在学习使用Java开发Web Service(不包括Restful)时,由于不知道Java有这么多框架支持开发Web Service一度陷入迷惘,不知道这些框架各有 什么不同,各有什么优缺点. ...

  3. 18.用两个栈实现队列[2StacksToImplementQueue]

    [题目] 某队列的声明如下:  C++ Code  123456789101112131415   template<typename T> class CQueue { public: ...

  4. UEditor去除复制样式实现无格式粘贴

    UEditor内置了无格式粘贴的功能,只需要简单的配置即可. 1.修改ueditor.config.js,开启retainOnlyLabelPasted,并设置为true 2.开启pasteplain ...

  5. 在cmd命令行中弹出Windows对话框

    有时候用bat写一些小脚本最后会弹出对话框提示操作成功,可以用mshta.exe来实现,它是Windows系统的相关程序,用来执行.HTA文件,一般计算机上面都有这个程序,实现如下: mshta vb ...

  6. 用php计算行列式

    因为有课程设计要计算多元一次方程组,所以想编个程序实现,多元一次方程组的计算最系统的方法就是利用克拉默法则求解方程组,所以只需要编写一个类或者方法求出多元一次方程组系数行列式的值和和其他几个行列式,如 ...

  7. 【xml】python的lxml库使用

    1.官方教程:http://lxml.de/tutorial.html#parsing-from-strings-and-files  最重要的文档,看完基本就能用了 2.lxml支持xpath,xp ...

  8. p235习题2

    List  成功添加 Set  添加失败

  9. 二叉树学习笔记之二叉查找树(BSTree)

    二叉查找树即搜索二叉树,或者二叉排序树(BSTree),学习回顾一下有关的知识. >>关于二叉查找树 二叉查找树(Binary Search Tree)是指一棵空树或者具有下列性质的二叉树 ...

  10. Android打Path的方法

    转自:http://blog.csdn.net/xiangzi10/article/details/42710099 作为程序员,了解diff&patch命 令是非常必要的.比如说我们发现某个 ...