5252: 英雄卡
Time Limit: 2 Sec Memory Limit: 128 MB
Submit: 133 Solved: 12
[Submit][Status][Web Board]
Description
小李非常迷恋收集各种干脆面里面的英雄卡,为此他曾经连续一个月都只吃干脆面这一种零食,但是有些稀有英雄卡真的是太难收集到了。后来某商场搞了一次英雄卡兑换活动,只要你有三张编号连续的英雄卡,你就可以换一张英雄卡。小李想知道他最多可以换到几张英雄卡(新换来的英雄卡不可以再次兑换)。
Input
第一行,共一个整数n,表示小李拥有的英雄卡数。
第二行,共n个空格隔开的数字a[i],表示英雄卡的编号。
Output
输出仅有一行,共1个整数,表示小李最多可以换到的英雄卡。
Sample Input
Sample Output
HINT
1 2 3三张编号连续,可以换一张,换完后剩下4 4 5,不符合兑换规则,无法继续兑换。
数据规模:1<=a[i],n<=200000
---------------------------------------------------------------------------------------------------------------------------------
利用数组存储所有卡牌的数量,再利用循环找到三张连号的牌。
#include<bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(0);
int a[200010]={0};
int x;
int n;
cin>>n;
int max_card=-1;
for(int i=0;i<n;i++)
{
cin>>x;
a[x]++;
if(x>max_card)
max_card=x;
}
int duihuan=0;
for(int i=0;i<max_card;i++)
{
if(a[i]>0)
if(a[i+1]>0)
if(a[i+2]>0)
a[i]--,a[i+1]--,a[i+2]--,i--,duihuan++;
//考虑到连号的牌可能有多张,所以i--返回再次查找
}
cout<<duihuan<<endl;
}
5253: 排队接水
Time Limit: 3 Sec Memory Limit: 128 MB
Submit: 61 Solved: 9
[Submit][Status][Web Board]
Description
有n个人在一个水龙头前排队接水,假如每个人接水的时间为Ti,请编程找出这n个人排队的一种顺序,使得n个人的平均等待时间最小。
Input
输入共两行,第一行为n;第二行输入n个数字,表示第1个人到第n个人每人的接水时间T1,T2,……,Tn,每个数据之间有1个空格。
Output
输出有两行,第一行为一种排队顺序,第i个数字代表第i个接水人的编号,行末不能有多余空格,即1到n的一种排列;第二行为这种排列方案下的平均等待时间(输出结果精确到小数点后两位)。
注意:输出排序时,当两人接水时间一样时,需要让编号小的人在前。
Sample Input
10 56 12 1 99 1000 234 33 55 99 812
Sample Output
3 2 7 8 1 4 9 6 10 5 291.90
HINT
N<=200000
1<=Ti<=10000000,ti有可能重复
---------------------------------------------------------------------------------------------------------------------------------
要让接水的平均时间最短,就要让总等待时间最短。那么就要进行排序,将接水所需等待时间短的人排在前面。我认为这道题的关键在于理解平均时间的计算。当第一个人在接水的时候,后面所有的人都在等第一个人接水。假如一共10个人,第一个人需要被等待1分钟,那么后面9个人都需要花费1分钟的等待时间,所以总等待时间应该加上9分钟。
#include<bits/stdc++.h>
using namespace std;
struct person
{
int id;
int time;
}per[200010];
bool cmp(person a,person b)
{
if(a.time==b.time)
return a.id<b.id;
return a.time<b.time;
}
int main()
{
ios::sync_with_stdio(0);
long long n;//long long重点
cin>>n;
long long a[n];//long long重点
for(int i=0;i<n;i++)
{
cin>>per[i].time;
per[i].id=i+1;
}
sort(per,per+n,cmp);
double sum=0;
for(int i=0;i<n;i++)
{
if(i==0)
cout<<per[i].id;
else
cout<<" "<<per[i].id;
sum+=per[i].time*(n-i-1);
}
cout<<endl;
printf("%.2lf\n",sum/n);
}
5254: 颜色叠加
Time Limit: 2 Sec Memory Limit: 128 MB
Submit: 145 Solved: 23
[Submit][Status][Web Board]
Description
热爱科学的Kimi这段时间在研究各种颜色,今天他打算做一个关于颜色叠加的小实验。 Kimi有很多张蓝色和黄色的长方形透明塑料卡片。众所周知,如果把蓝色和黄色混合在一起就会变成绿色。因此,Kimi对着光观察蓝色透明卡片和黄色透明卡片的叠加部分也就可以看到绿色啦。 假设在一个二维平面中,一张蓝色的透明卡片和一张黄色的透明卡片都与坐标轴平行放置,即卡片的横边与 x 轴平行,竖边与 y 轴平行。 现在给出一张蓝色卡片和一张黄色卡片的左上角坐标(均为整数)以及两张卡片的长和宽(均为正整数)。
注意:此处定义与 x 轴平行的那组边为长边,与 y 轴平行的那组边为宽边。
请编写一个程序计算这两张卡片叠加后所形成的绿色区域的面积。
Input
单组输入。 第 1 行输入四个整数,分别表示蓝色长方形透明卡片的左上角坐标( x 坐标和 y 坐标)、长和宽。两两之间用英文空格隔开。 第 2 行输入四个整数,分别表示黄色长方形透明卡片的左上角坐标( x 坐标和 y 坐标)、长和宽。两两之间用英文空格隔开。 两张长方形透明卡片的 x 坐标和 y 坐标的取值范围为[-1000, 1000],长和宽的取值范围为[1,200]。
Output
输出一个非负整数,表示两张卡片叠加后所形成的绿色区域的面积。
Sample Input
0 100 200 100 100 150 75 75
Sample Output
1875
---------------------------------------------------------------------------------------------------------------------------------
这道题粗略估计时间复杂度之后我选择用二维数组暴力循环来做,这样就避免了各种情况的分类讨论。
#include<bits/stdc++.h>
using namespace std;
int a[2410][2410]={0};
int main()
{
ios::sync_with_stdio(0);
int x1,y1,x2,y2;
int c1,k1,c2,k2;
cin>>x1>>y1>>c1>>k1;
cin>>x2>>y2>>c2>>k2;
for(int i=x1;i<x1+c1;i++)
//for(int j=y1;j<y1+k1;j++)
for(int j=y1-k1+1;j<=y1;j++)
{
a[i+1200][j+1200]++;
}
for(int i=x2;i<x2+c2;i++)
//for(int j=y2;j<y2+k2;j++)
for(int j=y2-k2+1;j<=y2;j++)
{
a[i+1200][j+1200]++;
}
int area=0;
for(int i=0;i<2410;i++)
{
for(int j=0;j<2410;j++)
{
if(a[i][j]==2)
area++;
}
}
cout<<area<<endl;
}
5255: 勤劳的老杨
Time Limit: 2 Sec Memory Limit: 128 MB
Submit: 26 Solved: 6
[Submit][Status][Web Board]
Description
勤劳的老杨最近收到了一个任务清单,在这个清单上有 n 项不同的工作任务。对于每一项任务都给出了两个时间 [x,y] ,其中 x 表示任务的起始时间(任务从第 x 天开始,包含第 x 天),y 表示任务的结束时间(任务到第 y 天结束,包含第 y 天)。 认真的老杨对待每一项任务都是一心一意的。一旦他决定做某一项任务,在该任务没有完成之前他不会同时再做另一项任务,也就是说在任意时刻老杨手头最多只有一项任务。 假设完成每一项任务所获得的报酬都是相等的。那么,老杨应该如何来安排自己的时间才可以得到最多的报酬呢? 请你编写一个程序帮老杨计算出他最多可以完成的任务数量。保证至少能完成一项任务。
Input
单组输入。
第 1 行输入一个正整数 n(n<=200000) 表示任务清单上任务的总数。
第 2 行到第 n+1 行每一行包含两个正整数x,y ,分别表示每一项任务的开始时间和结束时间,两个正整数之间用空格隔开,保证 1<= x,y<=10^9。
Output
输出老杨最多可以完成的任务数量。
Sample Input
7
1 4
1 3
2 7
3 4
4 6
5 10
7 8
Sample Output
3
HINT
对于输入样例,最多可以完成的任务数量为 3,对应 [1, 3] (第 2 项任务),[4, 6] (第 5 项任务)和 [7, 8] (第 7 项任务)这三项任务。
---------------------------------------------------------------------------------------------------------------------------------
选择越早结束的任务去完成,这样选择下一个任务就有更多的余地,这样就可以使完成任务的件数最大化。将任务定义为结构体,并依据任务结束时间进行升序排序。在选择任务的时候,根据下一个任务的开始时间是否大于本任务的结束时间来判断是否选择下一个任务。
#include<bits/stdc++.h>
using namespace std;
struct task
{
int b;
int e;
}t[200010];
bool cmp(task a,task b)
{
return a.e<b.e;
}
int main()
{
ios::sync_with_stdio(0);
int n;
cin>>n;
for(int i=0;i<n;i++)
cin>>t[i].b>>t[i].e;
sort(t,t+n,cmp);
int temp=0;
int sum=0;
for(int i=0;i<n;i++)
{
if(t[i].b>temp)
temp=t[i].e,sum++;
}
cout<<sum<<endl;
}
5256: 秘密大厦的访客
Time Limit: 3 Sec Memory Limit: 128 MB
Submit: 668 Solved: 56
[Submit][Status][Web Board]
Description
Kimi最近在负责一栋秘密大厦的安保工作,他的工作是记录大厦的来访者情况。
每个来访者都有一个与之对应的唯一编号,在每一条到访记录中记录了该来访者的编号。
现在Kimi需要统计每一条记录中的来访者是第几次光临秘密大厦。
Input
单组输入,包含两行。
第1行包含一个正整数 n,表示记录的条数;
第2行包含 n 个正整数,依次表示Kimi的记录中每位来访者的编号,两两之间用空格隔开。
保证 n 与来访者的编号都不超过 200000。
Output
输出 1 行,包含 n 个正整数,两两之间用空格隔开,依次表示每条记录中的来访者编号是第几次出现。
Sample Input
6
1 1 2 2 3 1
Sample Output
1 2 1 2 1 3
---------------------------------------------------------------------------------------------------------------------------------
建立一个数组用以存储数字出现次数,再将所有数字依次存入数组,存入一次就输出一次出现次数即可。
#include<bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(0);
int n;
cin>>n;
int a[200010]={0};
int x;
for(int i=0;i<n;i++)
{
cin>>x;
a[x]++;
if(i==0)
cout<<a[x];
else
cout<<" "<<a[x];
}
}