您的位置:首页 > 其它

HDU 4584Shaolin2012杭州全国邀请赛J题(暴力或set 两种做法)

2013-08-11 08:41 375 查看


Shaolin

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

Total Submission(s): 271    Accepted Submission(s): 141


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为1,有武力值10^9.然后后面会陆陆续续来弟子,每个来的人都会有自己的id,武力值。在它之前来的都是他的师父,从他的师父里找一个跟他武力值最接近的和他比赛,输出二者id。这样肯定不会有两个人武力值相同,不然找不到。如果两个师父最接近,找一个武力值比他小的人比赛。
 
                     解题思路:首先是暴力解题,不过需要转换一下,因为给的是id,但是来的顺序却不是按id排序的,所以我增加了一个com标志来的顺序。然后按照武力值排序。每次都找他的师父里离他最近的,pos1,pos2,表示往前看,往后看。不过实际上不需要判断那么多,因为肯定会有比它大的,因为方丈的武力值为10^9。具体见代码。

            题目地址:Shaolin

AC代码1:(暴力)
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdio>
#include<algorithm>
using namespace std;

struct nod
{
int a,b;
};
nod res[5000005];
struct node
{
int id,fig,com;
//com标记是第几个来的
};
node p[5000005];
int cmp(node a,node b)
{
if(a.fig<b.fig) return 1;
return 0;
}

int main()
{
int n,i,j;
while(scanf("%d",&n)&&n)
{
p[0].id=1;
p[0].fig=1000000000;
p[0].com=1;
for(i=1;i<=n;i++)
{
scanf("%d%d",&p[i].id,&p[i].fig);
p[i].com=i+1;
}

sort(p,p+n+1,cmp);
//需要的顺序是按come的顺序,先遍历一遍,再按come顺序输出
for(i=0;i<=n;i++)
{
int pos1=-1,pos2=-1;
for(j=i-1;j>=0;j--)
if(p[j].com<p[i].com)  //j是老和尚
{ pos1=j; break; }
for(j=i+1;j<=n;j++)
if(p[j].com<p[i].com)
{ pos2=j; break; }
res[p[i].com].a=p[i].id;
if(pos1==-1)
res[p[i].com].b=p[pos2].id;
else if(pos2==-1)
res[p[i].com].b=p[pos1].id;
else
{
int tmp=p[pos1].fig+p[pos2].fig-2*p[i].fig;
if(tmp>=0)
res[p[i].com].b=p[pos1].id;
else
res[p[i].com].b=p[pos2].id;
}
}

for(i=2;i<=n+1;i++)
printf("%d %d\n",res[i].a,res[i].b);
}
return 0;
}
//171MS 2228K


                另外还有一种是用set做的,每次都找离它最近的,直接是lower_bound,lower_bound-1.不过在没有找到比它小的值的时候,就是返回第一个(比他大的),会返回begin。具体见代码;

AC代码2:(set)
#include<iostream>
#include<string>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
int MAX=1000000000;

int main()
{
int n,id,fig;
set<int>mq;
set<int>::iterator it;
map<int,int>map1;
while(scanf("%d",&n),n)
{
mq.clear();
mq.insert(MAX);
map1.clear();
map1[MAX]=1;
for(int i=0;i<n;i++)
{
scanf("%d%d",&id,&fig);
it=mq.lower_bound(fig);  //比它大
if(it==mq.begin())
printf("%d %d\n",id,map1[*it]);
else
{
int tmp=*it; it--;
if(tmp+(*it)>=2*fig)
printf("%d %d\n",id,map1[*it]);
else
printf("%d %d\n",id,map1[tmp]);
}
mq.insert(fig);
map1[fig]=id;
}
}
}
//265MS 6540K


       下面是验证begin就是指向第一个元素的代码:
#include<iostream>
#include<string>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<map>
#include<set>
#include<algorithm>
using namespace std;

int main()
{
set<int> mq;
set<int>::iterator it;
//mq.insert(-2);
mq.insert(2);
mq.insert(5);
it=mq.lower_bound(0);
if(it==mq.begin())
{
cout<<"指在第一个元素begin,木有比0小的"<<endl;
cout<<*it<<endl;
//begin指向第一个元素
}
mq.insert(8);
it=mq.upper_bound(8);
if(it==mq.end())
{
cout<<"upper_bound是求比它大的最小值"<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: