hdu4585 Treap与名次树/STL map(C/C++)
hdu4585
题目地址:https://acm.dingbacode.com/showproblem.php?pid=4585
Shaolin
Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)
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.
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.
3
2 1
3 3
4 2
0
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++)的更多相关文章
- Treap 实现名次树
在主流STL版本中,set,map,都是BST实现的,具体来说是一种称为红黑树的动态平衡BST: 但是在竞赛中并不常用,因为红黑树过于复杂,他的插入 5 种,删除 6 中,代码量极大(如果你要改板子的 ...
- Treap和名次树
Treap名字的来源:Tree+Heap,正如名字一样,就是一颗简单的BST,一坨堆的合体.BST的不平衡的根本原因在于基于左<=根<=右的模式吃单调序列时候会无脑成长链,而Treap则添 ...
- 模板——Treap实现名次树
Treap 是一种通过赋予结点随机权值的一种满足堆性质的二叉搜索树,它很好的解决了二叉搜索树顺序插入组成链式的局限性. 名次树是指在treap的每个结点中添加附加域size,表示以它为根的子树的总结点 ...
- 「模板」「讲解」Treap名次树
Treap实现名次树 前言 学平衡树的过程可以说是相当艰难.浏览Blog的过程中看到大量指针版平衡树,不擅长指针操作的我已经接近崩溃.于是,我想着一定要写一篇非指针实现的Treap的Blog. 具体如 ...
- bzoj3224 Tyvj 1728 普通平衡树(名次树+处理相同)
3224: Tyvj 1728 普通平衡树 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 5354 Solved: 2196[Submit][Sta ...
- STL MAP及字典树在关键字统计中的性能分析
转载请注明出处:http://blog.csdn.net/mxway/article/details/21321541 在搜索引擎在通常会对关键字出现的次数进行统计,这篇文章分析下使用C++ STL中 ...
- uvalive 5031 Graph and Queries 名次树+Treap
题意:给你个点m条边的无向图,每个节点都有一个整数权值.你的任务是执行一系列操作.操作分为3种... 思路:本题一点要逆向来做,正向每次如果删边,复杂度太高.逆向到一定顺序的时候添加一条边更容易.详见 ...
- UVa 1479 (Treap 名次树) Graph and Queries
这题写起来真累.. 名次树就是多了一个附加信息记录以该节点为根的树的总结点的个数,由于BST的性质再根据这个附加信息,我们可以很容易找到这棵树中第k大的值是多少. 所以在这道题中用一棵名次树来维护一个 ...
- LA 5031 Graph and Queries —— Treap名次树
离线做法,逆序执行操作,那么原本的删除边的操作变为加入边的操作,用名次树维护每一个连通分量的名次,加边操作即是连通分量合并操作,每次将结点数小的子树向结点数大的子树合并,那么单次合并复杂度O(n1lo ...
- bzoj 3196 Tyvj 1730 二逼平衡树(线段树套名次树)
3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1807 Solved: 772[Submit][Stat ...
随机推荐
- IaaS--云硬盘(何恺铎《深入浅出云计算》笔记整理)
[概念] 云硬盘,又叫做"云盘"或者"云磁盘",就是云虚拟机上可以挂载和使用的硬盘.这里,它既包含了用于承载操作系统的系统盘,也包括了承载数据的数据盘.云厂商对 ...
- parted创建硬盘分区并创建LVM
基本分区创建分区只有那么大,无法调整大小,写入数据占满时便无法继续,而LVM特点就是可随意扩张大小,避免磁盘占满导致数据丢失. 查看磁盘lsblk 对磁盘进行分区 [root@localhost ~ ...
- vs code 提交代码弹框提示:请确保已在git中配置您的“user.name”和“user.email” ——解决方法
修改完项目代码,准备提交到git上,结果提交失败,弹框提示:请确保已在Git中配置您的"user.name"和"user.email" 打开终端,配置运行一下命 ...
- SourceInsight4.0修改字体大小
SourceInsight4.0修改字体大小 1.右键Options->Preferences.如图所示,然后找到Syntax Decorations选项,点击File Types 2.点击Fi ...
- 安装netbense时提示在此计算机中找不到Java SE开发工具包(JDK)
在提示信息中显示的需要JDK8或更高版本,这边需要提醒大家不要把jdk8和jdk1.8弄混 首先大家打开控制面板找到程序并点击进去 点击程序和功能 在电脑上查看是否有java8或更高版本的内容如果没有 ...
- check power supply check cpu top
lshw -c power power supply mwh https://www.eia.gov/energyexplained/electricity/electricity-in-the-us ...
- 【git】3.2git分支-分支的新建与合并
资料来源 (1) https://git-scm.com/book/zh/v2/Git-%E5%88%86%E6%94%AF-%E5%88%86%E6%94%AF%E7%9A%84%E6%96%B0% ...
- 总结ref和out的区别
之前每次遇到ref和out时,老是忘记他们的使用方法和区别.每次都要网上搜一下别人写的博客来回忆.这次干脆自己整合一下别人博客的内容,方便下次忘记时查询. 用途: 在C#中通过使用方法来获取返回值时, ...
- Java反射获取方法参数名
正常环境下,获取不到参数的名称,使用java反射时,第一个参数名是arg0,第二个参数是arg1,与我们代码中写的对不上. java反射过程中,需要我们做好判断: if(!parameter.is ...
- leetcode-152乘积最大子数组(两个转移方程的正确性证明)
1.dp数组的含义 maxDP[i]中存储 以nums[i]为结尾元素的子数组的最大乘积minDP[i]中存储 以nums[i]为结尾元素的子数组的最小乘积 注意到:maxDP[i] >= mi ...