zoukankan      html  css  js  c++  java
  • 【BZOJ】1862: [Zjoi2006]GameZ游戏排名系统 & 1056: [HAOI2008]排名系统(treap+非常小心)

    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
    ", 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

  • 相关阅读:
    Hibernate的入门Curd用法
    使用Struts2实现图片上传和拦截器
    Layui连接mysql操作CRUD案例
    Struts2连接Mysql的Crud使用
    Struts2中OGNL表达式的用法
    Struts2简介、初步使用
    Maven配置、使用
    Web前后端分离开发(CRUD)及其演变概括
    堆的建立、调整、删除、插入
    set(集合)的使用方法
  • 原文地址:https://www.cnblogs.com/iwtwiioi/p/3937517.html
Copyright © 2011-2022 走看看