ZCMU--1487: 红桃X(二分做法)

Description

从西安到杭州的火车实在是太漫长了,为了打发时间,H买了n张扑克牌 (一张一张卖的你们没见过吧¯▽¯) 牌面大小为 3....,9,10,J,Q,K,A,2,现在告诉你n张扑克牌的牌面(已按照从小到大的顺序理好),你能告诉我第k张红桃X在哪个位置吗?题目保证H买的牌全都是红桃的

Input

输入多组数据

第一行输入一个n (1<=n<=100000)表示H买了n张牌

第二行输入n个字符 a1,a2,a3,....,an

第三行输入一个数m(1<=m<=100000) 表示有m次询问

接下来m行每行输入一个整数k(1<=k<=n)和字符X

Output

输出第k张红桃X所在的位置,如果牌不存在则输出-1,每个输出占一行

Sample Input

5
3 9 9 J 2
5
1 3
2 3
2 9
1 2
1 J

Sample Output

1
-1
3
5
4

解析:我们可以将他们变成3~15的数,读入完排序一次,对于每个询问二分查找位置即可,对于-1的情况,我们可以利用一个一个cnt[ ]记录一下每个数字出现的次数,如果对应牌的总数小于要求,就直接-1,否则肯定能二分找到,这样我们就不用考虑什么特殊情况了

#include <cstdio>
#include <algorithm>
using namespace std;	
const int N=1e5+5;
int a[N],cnt[18];
int main()
{
	int n,m;
	while(~scanf("%d",&n))
	{
		for(int i=3;i<=15;i++) cnt[i]=0;//多组初始化 
		for(int i=1;i<=n;i++)
		{
			char k[3];
			scanf("%s",k);
			if(k[0]>='3'&&k[0]<='9') a[i]=k[0]-'0';
			else if(k[0]=='J') a[i]=11;
			else if(k[0]=='Q') a[i]=12;
			else if(k[0]=='K') a[i]=13;
			else if(k[0]=='A') a[i]=14;
			else if(k[0]=='2') a[i]=15;
			else a[i]=10;
			cnt[a[i]]++;//对应牌数量+1 
		}
		sort(a+1,a+n+1);
		scanf("%d",&m);
		while(m--)
		{
			int x,y;//第x张y牌 
			char k[3];
			scanf("%d %s",&x,k);
			if(k[0]>='3'&&k[0]<='9') y=k[0]-'0';
			else if(k[0]=='J') y=11;
			else if(k[0]=='Q') y=12;
			else if(k[0]=='K') y=13;
			else if(k[0]=='A') y=14;
			else if(k[0]=='2') y=15;
			else y=10;
			if(x>cnt[y])//-1情况 
			{
				printf("-1\n");
				continue;
			}
			int l=1,r=n,pos;
			while(l<=r)//二分找第一个y牌的位置 
			{
				int mid=l+r>>1;
				if(y<=a[mid]) pos=mid,r=mid-1;
				else l=mid+1;
			}
			printf("%d\n",pos+x-1);//那么第x张就是pos+x-1 
		}
	}
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值