hdu4585

题目地址:https://acm.dingbacode.com/showproblem.php?pid=4585

Shaolin

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)


Problem Description
Shaolin temple is very famous for its Kongfu monks.A lot of young men go to Shaolin temple every year, trying to be a monk there. The master of Shaolin evaluates a young man mainly by his talent on understanding the Buddism scripture, but fighting skill is also taken into account.
When a young man passes all the tests and is declared a new monk of Shaolin, there will be a fight , as a part of the welcome party. Every monk has an unique id and a unique fighting grade, which are all integers. The new monk must fight with a old monk whose fighting grade is closest to his fighting grade. If there are two old monks satisfying that condition, the new monk will take the one whose fighting grade is less than his.
The master is the first monk in Shaolin, his id is 1,and his fighting grade is 1,000,000,000.He just lost the fighting records. But he still remembers who joined Shaolin earlier, who joined later. Please recover the fighting records for him.

 
Input
There are several test cases.
In each test case:
The first line is a integer n (0 <n <=100,000),meaning the number of monks who joined Shaolin after the master did.(The master is not included).Then n lines follow. Each line has two integer k and g, meaning a monk's id and his fighting grade.( 0<= k ,g<=5,000,000)
The monks are listed by ascending order of jointing time.In other words, monks who joined Shaolin earlier come first.
The input ends with n = 0.

 
Output
A fight can be described as two ids of the monks who make that fight. For each test case, output all fights by the ascending order of happening time. Each fight in a line. For each fight, print the new monk's id first ,then the old monk's id.

 
Sample Input
3
2 1
3 3
4 2
0
Sample Output
2 1
3 2
4 2

题意

先对老和尚的等级排序,在加入一个新和尚是,找到等级最接近的老和尚,输出老和尚的id。

总复杂度O(nlong n)

<解法一> STL map

AC代码

 1 #include<bits/stdc++.h>
2 using namespace std;
3 const int maxn=1e9;
4 map<int,int> mp;//it->first是等级,it->second是id
5 int main(){
6 int n;
7 while(~scanf("%d",&n)&&n){
8 mp.clear();
9 mp[maxn]=1;//方丈1,等级是1 000 000 000
10 while(n--){
11 int id,g;
12 scanf("%d%d",&id,&g);//新和尚id,等级是g
13 mp[g]=id;//进队
14 int ans;
15 map<int,int>::iterator it=mp.find(g);//找到排好序的位置
16 if(it==mp.begin()) ans=(++it)->second;
17 else{
18 map<int,int>::iterator it2=it;
19 it2--;it++;//等级接近的前后两个老和尚
20 if(g-it2->first<=it->first-g)
21 ans=it2->second;
22 else ans=it->second;
23 }
24 printf("%d %d\n",id,ans);
25 }
26 }
27 return 0;
28 }

<解法二> Treap树

AC代码

 1 #include<bits/stdc++.h>
2 using namespace std;
3 int id[5000005];
4 struct node{
5 int size;//以这个结点为根的子树的结点总数量,用于名次树
6 int rank;//优先级
7 int key;//键值
8 node *son[2];//son[0]是左儿子,son[1]是右儿子
9 bool operator<(const node &a)const{return rank<a.rank;}
10 int cmp(int x)const{
11 if(x==key) return -1;
12 return x<key?0:1;
13 }
14 void update(){//更新size
15 size=1;
16 if(son[0]!=NULL) size+=son[0]->size;
17 if(son[1]!=NULL) size+=son[1]->size;
18 }
19 };
20 void rotate(node *&o,int d){//d=0,左旋;d=1,右旋
21 node *k=o->son[d^1];//d^1与1-d等价,但是更快
22 o->son[d^1]=k->son[d];
23 k->son[d]=o;
24 o->update();
25 k->update();
26 o=k;
27 }
28 void insert(node *&o,int x){//把x插入到树中
29 if(o==NULL){
30 o=new node();
31 o->son[0]=o->son[1]=NULL;
32 o->rank=rand();
33 o->key=x;
34 o->size=1;
35 }
36 else{
37 int d=o->cmp(x);
38 insert(o->son[d],x);
39 o->update();
40 if(o<o->son[d]) rotate(o,d^1);
41 }
42 }
43 int kth(node *o,int k){//返回第k大的数
44 if(o==NULL||k<=0||k>o->size) return -1;
45 int s=o->son[1]==NULL?0:o->son[1]->size;
46 if(k==s+1) return o->key;
47 else if(k<=s) return kth(o->son[1],k);
48 else return kth(o->son[0],k-s-1);
49 }
50 int find(node *o,int k){//返回元素k的名次
51 if(o==NULL) return -1;
52 int d=o->cmp(k);
53 if(d==-1) return o->son[1]==NULL?1:o->son[1]->size+1;
54 else if(d==1) return find(o->son[d],k);
55 else{
56 int tmp=find(o->son[d],k);
57 if(tmp==-1) return -1;
58 else return o->son[1]==NULL?tmp+1:tmp+1+o->son[1]->size;
59 }
60 }
61 int main(){
62 int n;
63 while(~scanf("%d",&n)&&n){
64 srand(time(NULL));
65 int k,g;
66 scanf("%d%d",&k,&g);
67 node *root=new node();
68 root->son[0]=root->son[1]=NULL;
69 root->rank=rand();
70 root->key=g;
71 root->size=1;
72 id[g]=k;
73 printf("%d 1\n",k);
74 for(int i=2;i<=n;i++){
75 scanf("%d%d",&k,&g);
76 id[g]=k;
77 insert(root,g);
78 int t=find(root,g);//返回新和尚的名次
79 int ans1,ans2,ans;
80 ans1=kth(root,t-1);//前一名的老和尚
81 ans2=kth(root,t+1);//后一名的老和尚
82 if(ans1!=-1&&ans2!=-1) ans=ans1-g>=g-ans2?ans2:ans1;
83 else if(ans1==-1) ans=ans2;
84 else ans=ans1;
85 printf("%d %d\n",k,id[ans]);
86 }
87 }
88 return 0;
89 }

感觉这段比较难理解的话,可以去看看《算法竞赛入门经典训练指南》(蓝书)P230的3.5.2

函数?拿来吧你

// 讲真,发生了一件比较诡异的事情,我在之前的博客里不是写过一次rotate函数嘛,然后把那边的rotate函数直接复制过来(当然要加上更新,而且必须是先维护o,再维护k)去交的话CE了,但是重打一遍就AC了。。。就离谱/笑哭//笑哭//笑哭/

// 上面提到的之前的博客的地址:https://www.cnblogs.com/ynzhang2020/p/15070994.html

hdu4585 Treap与名次树/STL map(C/C++)的更多相关文章

  1. Treap 实现名次树

    在主流STL版本中,set,map,都是BST实现的,具体来说是一种称为红黑树的动态平衡BST: 但是在竞赛中并不常用,因为红黑树过于复杂,他的插入 5 种,删除 6 中,代码量极大(如果你要改板子的 ...

  2. Treap和名次树

    Treap名字的来源:Tree+Heap,正如名字一样,就是一颗简单的BST,一坨堆的合体.BST的不平衡的根本原因在于基于左<=根<=右的模式吃单调序列时候会无脑成长链,而Treap则添 ...

  3. 模板——Treap实现名次树

    Treap 是一种通过赋予结点随机权值的一种满足堆性质的二叉搜索树,它很好的解决了二叉搜索树顺序插入组成链式的局限性. 名次树是指在treap的每个结点中添加附加域size,表示以它为根的子树的总结点 ...

  4. 「模板」「讲解」Treap名次树

    Treap实现名次树 前言 学平衡树的过程可以说是相当艰难.浏览Blog的过程中看到大量指针版平衡树,不擅长指针操作的我已经接近崩溃.于是,我想着一定要写一篇非指针实现的Treap的Blog. 具体如 ...

  5. bzoj3224 Tyvj 1728 普通平衡树(名次树+处理相同)

    3224: Tyvj 1728 普通平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 5354  Solved: 2196[Submit][Sta ...

  6. STL MAP及字典树在关键字统计中的性能分析

    转载请注明出处:http://blog.csdn.net/mxway/article/details/21321541 在搜索引擎在通常会对关键字出现的次数进行统计,这篇文章分析下使用C++ STL中 ...

  7. uvalive 5031 Graph and Queries 名次树+Treap

    题意:给你个点m条边的无向图,每个节点都有一个整数权值.你的任务是执行一系列操作.操作分为3种... 思路:本题一点要逆向来做,正向每次如果删边,复杂度太高.逆向到一定顺序的时候添加一条边更容易.详见 ...

  8. UVa 1479 (Treap 名次树) Graph and Queries

    这题写起来真累.. 名次树就是多了一个附加信息记录以该节点为根的树的总结点的个数,由于BST的性质再根据这个附加信息,我们可以很容易找到这棵树中第k大的值是多少. 所以在这道题中用一棵名次树来维护一个 ...

  9. LA 5031 Graph and Queries —— Treap名次树

    离线做法,逆序执行操作,那么原本的删除边的操作变为加入边的操作,用名次树维护每一个连通分量的名次,加边操作即是连通分量合并操作,每次将结点数小的子树向结点数大的子树合并,那么单次合并复杂度O(n1lo ...

  10. bzoj 3196 Tyvj 1730 二逼平衡树(线段树套名次树)

    3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1807  Solved: 772[Submit][Stat ...

随机推荐

  1. 统信系统部署es

    rpm -ivh jdk-17.0.4.1_linux-x64_bin.rpm groupadd es && useradd -d /home/es -g es estar -xzvf ...

  2. Android Studio 修改jar包中的.class代码

    修改a.jar中的b.class文件: 1.在Android Studio的项目中引入a.jar,sync,通过反编译找到并拷贝b.java的代码 2.使用压缩软件打开a.jar,并删掉需要修改的文件 ...

  3. C++的右值引用是左值,rvalue reference is lvalue.

    参考: https://stackoverflow.com/questions/28483250/rvalue-reference-is-treated-as-an-lvalue

  4. 实验室服务器运维踩坑o.0

    先说背景:实验室新配了一台Dell T640服务器,双3090, 512G内存, 5 x 8T硬盘(RAID5),2 x 1T固态(RAID1),配置很够用但就是搭建运维踩了很多坑,以下是主要完成的几 ...

  5. 玩玩 Visual Studio Code 和 MSYS2

    注意:为了便于理解本文内容,您可能需要一些前置知识,例如命令行操作,编译器操作,路径操作,环境变量操作,vscode操作-- 众所周知 Visual Studio Code 是一个优秀的编辑器. 众所 ...

  6. linux部署带ssl的nginx

    1.前期准备 1.1:下载nginx-1.18.0版本  http://nginx.org/download/nginx-1.18.0.tar.gz 然后上传到服      务器 /usr/local ...

  7. Centos+django+uwsgi+python 环境搭建

    首先需要具备linux的基本操作. centos 6.x 版本默认安装的 python 版本为2.x 输入: [root@dev ~]# python -VPython 2.6.6 下面装一些用到的库 ...

  8. mybatis bind 标签 覆盖 复杂对象的某个属性值 问题。

    需求: 有四个sql 都需要用一个 相同的where 条件,于是定义了一个sql 标签. 然后在每个sql中使用 <include refid="myWhereSql"> ...

  9. MogDB 学习笔记之 -- truncate 属于dml语句

    # 概念描述验证create 语句.alter 语句.truncate语句.drop语句 是属于ddl 还是dml # 测试验证 1.环境准备 ```修改log_statement 参数miao=# ...

  10. 此平台不支持虚拟化的 Intel VT-x/EPT。不使用虚拟化的 Intel VT-x/EPT,是否继续?

    1.cpu虚拟化是否打开 2.Windows安全中心>设备安全性>内核隔离