第k小整数
题目链接:https://nanti.jisuanke.com/t/T1670
现有 n 个正整数,要求出这 n 个正整数中的第 k 小的整数(相同大小的整数只计算一次)。
题解:set模拟
#include<bits/stdc++.h>
using namespace std;
#define maxn 505
#define maxm 500005
#define inf 2000000000123456789
#define IOS ios::sync_with_stdio(false)
#define ll long long
int main()
{
//IOS;
int n,m;
scanf("%d%d",&n,&m);
set<int>ss;
for(int i=0;i<n;i++)
{
int x;
scanf("%d",&x);
ss.insert(x);
}
int cnt=0;
int ans;
bool flag=false;
for(set<int>::iterator p=ss.begin();p!=ss.end();p++)
{
cnt++;
if(cnt==m)
{
ans=(*p);
flag=true;
break;
}
}
if(flag)
{
printf("%d\n",ans);
}
else
printf("NO RESULT\n");
return 0;
}
报数
题目链接:https://nanti.jisuanke.com/t/T1475
有 n 人围成一圈,顺序排号。从第 1个人开始报数(从 1 到 3 报数),凡报到 3 的人退出圈子,问最后留下的是原来的第几号。
题解:队列模拟
#include<bits/stdc++.h>
using namespace std;
#define maxn 505
#define maxm 500005
#define inf 2000000000123456789
#define IOS ios::sync_with_stdio(false)
#define ll long long
int main()
{
//IOS;
int n;
scanf("%d",&n);
queue<int>que;
for(int i=1;i<=n;i++)
que.push(i);
int time=0;
while(que.size()!=1)
{
time++;
time%=3;
int tt=que.front();
que.pop();
if(time==0)
time=3;
else
que.push(tt);
}
cout<<que.front();
return 0;
}
卡片游戏
题目链接:https://nanti.jisuanke.com/t/T1464
桌上有一叠牌,从第一张牌(即位于顶面的牌)开始从上往下依次编号为 1∼n。当至少还剩两张牌时进行以下操作:把第一张牌扔掉,然后把新的第一张放到整叠牌的最后。输入 n ,输出每次扔掉的牌,以及最后剩下的牌。
题解:队列模拟
#include<bits/stdc++.h>
using namespace std;
#define maxn 505
#define maxm 500005
#define inf 2000000000123456789
#define IOS ios::sync_with_stdio(false)
#define ll long long
int main()
{
//IOS;
int T;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
queue<int>que;
for(int i=1; i<=n; i++)
que.push(i);
vector<int>ans;
while(que.size()>1)
{
ans.push_back(que.front());
que.pop();
que.push(que.front());
que.pop();
}
if(!que.empty())
ans.push_back(que.front());
for(int i=0;i<ans.size();i++)
{
printf("%d",ans[i]);
if(i!=ans.size()-1)
printf(" ");
}
printf("\n");
}
return 0;
}
找球号
题目链接:https://nanti.jisuanke.com/t/T1413
题意:找某一个数字是否存在,有重复数字。
题解:由于map和multiset超时,用unordered_map优化
#include<bits/stdc++.h>
using namespace std;
#define maxn 505
#define maxm 500005
#define inf 2000000000123456789
#define IOS ios::sync_with_stdio(false)
#define ll long long
int main()
{
//IOS;
int n,m;
scanf("%d%d",&n,&m);
unordered_map<int,int>ss;
for(int i=0;i<n;i++)
{
int x;
scanf("%d",&x);
ss[x]++;
}
for(int i=0;i<m;i++)
{
int x;
scanf("%d",&x);
if(ss.find(x)!=ss.end())
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
Set
题目链接:https://nanti.jisuanke.com/t/T1229
现有一整数集(允许有重复元素),初始为空。我们定义如下操作:
add x 把 x 加入集合
del x 把集合中所有与 x 相等的元素删除
ask x 对集合中元素x的情况询问
对每种操作,我们要求进行如下输出。
add 输出操作后集合中 x 的个数
del 输出操作前集合中 x 的个数
ask 先输出 0 或 1 表示 x 是否曾被加入集合(0 表示不曾加入),再输出当前集合中 x 的个数,中间用空格格开。
题解:虽然题目是set,但是需要记录某一个元素的个数,则用map更方便,主要注意一下删除操作,删除某一迭代器,则该迭代器失效,不能再使用。
#include<bits/stdc++.h>
using namespace std;
#define maxn 505
#define maxm 500005
#define inf 2000000000123456789
#define IOS ios::sync_with_stdio(false)
#define ll long long
map<int,int>mm1;
map<int,int>mm2;
int main()
{
//IOS;
int n;
scanf("%d",&n);
while(n--)
{
char str[6];
int x;
scanf("%s%d",str,&x);
if(strcmp(str,"add")==0)
{
mm1[x]++;
mm2[x]++;
printf("%d\n",mm1[x]);
}
if(strcmp(str,"del")==0)
{
map<int,int>::iterator p=mm1.find(x);
if(p!=mm1.end())
{
printf("%d\n",(*p).second);
mm1.erase(p);
}
else
printf("0\n");
}
if(strcmp(str,"ask")==0)
{
if(mm2[x]!=0)
printf("1 %d\n",mm1[x]);
else printf("0 0\n");
}
}
return 0;
}
热血格斗场
题目:https://nanti.jisuanke.com/t/T1230
蒜头君新开了一家热血格斗场。格斗场实行会员制,但是新来的会员不需要交入会费,而只要同一名老会员打一场表演赛,证明自己的实力。
我们假设格斗的实力可以用一个正整数表示,成为实力值。另外,每个人都有一个唯一的 id,也是一个正整数。为了使得比赛更好看,每一个新队员都会选择与他实力最为接近的人比赛,即比赛双方的实力值之差的绝对值越小越好,如果有两个人的实力值与他差别相同,则他会选择比他弱的那个(显然,虐人必被虐好)。
不幸的是,蒜头君一不小心把比赛记录弄丢了,但是他还保留着会员的注册记录。现在请你帮蒜头君恢复比赛纪录,按照时间顺序依次输出每场比赛双方的 id。
题解:注意两个条件:1、id唯一无重复 2、实力值唯一无重复。用map实现:map<key,value>,key设为实力值,value设为id。需要找与某一个值的差值最小,不妨在map中先插入这个值,因为map自带排序功能,所以只要比较插入这个位置左边和右边的值与的差值即可。
#include<bits/stdc++.h>
using namespace std;
#define maxn 505
#define maxm 500005
#define inf 2000000000123456789
#define IOS ios::sync_with_stdio(false)
#define ll long long
map<int,int>mm;
int main()
{
//IOS;
int n;
scanf("%d",&n);
mm[1000000000]=1;
while(n--)
{
int id,score;
scanf("%d%d",&id,&score);
mm[score]=id;
map<int,int>::iterator p=mm.find(score);
map<int,int>::iterator p0=p;
map<int,int>::iterator p1=p;
if(p!=mm.begin())
p0--;
if(p!=mm.end())
p1++;
int len1=(*p).first-(*p0).first;
int len2=(*p1).first-(*p).first;
if(len1==0)
printf("%d %d\n",(*p).second,(*p1).second);
else if(len2==0)
printf("%d %d\n",(*p).second,(*p0).second);
else
{
if(len1<len2)
printf("%d %d\n",(*p).second,(*p0).second);
else if(len1>len2)
printf("%d %d\n",(*p).second,(*p1).second);
else
{
if((*p1).first<(*p0).first)
printf("%d %d\n",(*p).second,(*p1).second);
else
printf("%d %d\n",(*p).second,(*p0).second);
}
}
}
return 0;
}
冷血格斗场
题目:https://nanti.jisuanke.com/t/T1231
蒜头君新开了一家冷血格斗场。格斗场实行会员制,但是新来的会员不需要交入会费,而只要同一名老会员打一场表演赛,证明自己的实力。
我们假设格斗的实力可以用一个正整数表示,成为实力值,两人的实力值可以相同。另外,每个人都有一个唯一的id,也是一个正整数。为了使得比赛更好看,每一个新队员都会选择与他实力最为接近的人比赛,即比赛双方的实力值之差的绝对值越小越好,如果有多个人的实力值与他差别相同,则他会选择id 最小的那个。
不幸的是,蒜头君一不小心把比赛记录弄丢了,但是他还保留着会员的注册记录。现在请你帮蒜头君恢复比赛纪录,按照时间顺序依次输出每场比赛双方的 id。
题解:与前一个题的区别为:1、实力值可以重复 2、差值相同的情况,输出id较小的。map 内置 优先队列:map键值对<key,value> ,value 设为优先队列,存key相同的id,并且按照从小到大排列。出现相同实力差时,比较时弹出最小的id即可(优先队列top)。因为总的n没有变,所以复杂度也没变 O(nlog(n))。
#include<bits/stdc++.h>
using namespace std;
#define maxn 505
#define maxm 500005
#define inf 2000000000123456789
#define IOS ios::sync_with_stdio(false)
#define ll long long
map<int,priority_queue<int,vector<int>,greater<int> > >mm;
int main()
{
//IOS;
int n;
scanf("%d",&n);
mm[1000000000].push(1);
while(n--)
{
int id,score;
scanf("%d%d",&id,&score);
if(mm[score].size()>0)
{
printf("%d %d\n",id,mm[score].top());
mm[score].push(id);
continue;
}
mm[score].push(id);
map<int,priority_queue<int,vector<int>,greater<int> > >::iterator p=mm.find(score);
map<int,priority_queue<int,vector<int>,greater<int> > >::iterator p0=p;
map<int,priority_queue<int,vector<int>,greater<int> > >::iterator p1=p;
if(p!=mm.begin())
p0--;
if(p!=mm.end())
p1++;
int len1=(*p).first-(*p0).first;
int len2=(*p1).first-(*p).first;
if(len1==0)
printf("%d %d\n",(*p).second.top(),(*p1).second.top());
else if(len2==0)
printf("%d %d\n",(*p).second.top(),(*p0).second.top());
else
{
if(len1<len2)
printf("%d %d\n",(*p).second.top(),(*p0).second.top());
else if(len1>len2)
printf("%d %d\n",(*p).second.top(),(*p1).second.top());
else
{
if((*p1).second.top()<(*p0).second.top())
printf("%d %d\n",(*p).second.top(),(*p1).second.top());
else
printf("%d %d\n",(*p).second.top(),(*p0).second.top());
}
}
}
return 0;
}