洛谷 P1918 保龄球 题解

题目描述

DL 算缘分算得很烦闷,所以常常到体育馆去打保龄球解闷。因为他保龄球已经打了几十年了,所以技术上不成问题,于是他就想玩点新花招。

DL 的视力真的很不错,竟然能够数清楚在他前方十米左右每个位置的瓶子的数量。他突然发现这是一个炫耀自己好视力的借口——他看清远方瓶子的个数后从某个位置发球,这样就能打倒一定数量的瓶子。

  1. ◯◯◯◯◯◯

  2. ◯◯◯ ◯◯◯◯ ◯

  3. ◯◯

  4. ◯ ◯◯ ◯

如上图,每个 “◯◯” 代表一个瓶子。如果 DL 想要打倒 33 个瓶子就在 11 位置发球,想要打倒 44 个瓶子就在 22 位置发球。

现在他想要打倒 mm 个瓶子。他告诉你每个位置的瓶子数,请你给他一个发球位置。

输入格式

第一行包含一个正整数 nn,表示位置数。

第二行包含 nn 个正整数 aiai​ ,表示第 ii 个位置的瓶子数,保证各个位置的瓶子数不同。

第三行包含一个正整数 QQ,表示 DL 发球的次数。

第四行至文件末尾,每行包含一个正整数 mm,表示 DL 需要打倒 mm 个瓶子。

输出格式

共 QQ 行。每行包含一个整数,第 ii 行的整数表示 DL 第 ii 次的发球位置。若无解,则输出 00。

输入输出样例

输入 #1复制

5
1 2 4 3 5
2
4
7

输出 #1复制

3
0

样例解释:查找两个数:4和7,4在第三个位置出现,而7从未出现,输出0。

说明/提示

【数据范围】

对于 50%50% 的数据,1≤n,Q≤1000,1≤ai,m≤10的五次方1≤n,Q≤1000,1≤ai​,m≤10的五次方。

对于 100%100% 的数据,1≤n,Q≤100000,1≤ai,m≤10的9次方1≤n,Q≤100000,1≤ai​,m≤10的9次方。

题解:

首先我们考虑的是暴力,来看最简单的代码:

#include <bits/stdc++.h>
using namespace std;
int n;
int a[100010];
int main()
{
    cin>>n;
    for(int i=0;i<n;i++)
    {
        cin>>a[i];
    }
    int q;
    cin>>q;
    for(int i=0;i<q;i++)
    {
        int x;cin>>x;
        bool flag=true;
        for(int j=0;j<n;j++)
        {
            if(a[j]==x)
            {
                cout<<j+1<<endl;
                flag=false;

            }
        }
        if(flag) cout<<0<<endl;
    }
    return 0;
}

恭喜你写出了代码,不过此题数据太肉了,双重循环的时间复杂度就会飙升100亿。QWQ~~~~~~

那么,正片开始

正解:

方法一:STL大法!

众所周知,map是个好东西,它可以通过变量的映射帮我们解决一大堆问题。推荐:大佬map详解

我们先定义一个map数组,把的数值与编号互相映射。在输入查找的数时,直接调用map输出编号,千言万语不如你们想要的代码:

#include <bits/stdc++.h>
using namespace std;
map<int,int> mp;
int n;
int a[100010];
int main()
{
    cin>>n;
    for(int i=0;i<n;i++)
    {
        cin>>a[i];
        mp[a[i]]=i+1;
    }
    int q;
    cin>>q;
    for(int i=0;i<q;i++)
    {
        int x;
        cin>>x;
        cout<<mp[x]<<endl;
    }
    return 0;
}

这样,就可以快乐AC了!那么接下来……

方法二:二分

二分算法是人尽皆知的,不过人尽皆会用,恐怕做不到。不过贴心得我又准备了大佬的详解:二分详解

OK详解你们肯定看过了吧,接下来,我来帮你们梳理一下:

首先使用结构体存储,不会有人不会结构体吧。

结构体详解

然后,我们就使用二分查找来得出答案:

#include<bits/stdc++.h>
using namespace std;
struct pos{
	int num;
	int sum;
}a[100005];
bool cmp(pos x,pos y)
{
	return x.sum <y.sum; 
}
int main(){
	int n,m,q;
	cin>>n;
	for(int i=1;i<=n;i++)
    {
		cin>>a[i].sum ;
		a[i].num= i;
	}
	sort(a+1,a+1+n,cmp);
	cin>>m;
	for(int i=1;i<=m;i++)
    {
		cin>>q;
		int l=1,r=n,ans=0;
		while(l<=r)
        {
			int mid=(l+r)/2;
			if(a[mid].sum<=q)
            {
				l=mid+1;
				ans=mid;
			}
			else
            {
				r=mid-1;
			}
		}
		if(a[ans].sum==q) cout<<a[ans].num<<endl;
		else cout<<0<<endl;
		 
	}
	return 0; 

好了这就是这道题的题解,大家看懂了不要忘记点赞关注一下吧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值