C++-抢气球 解题思路
【Horn Studio】编程专栏: 抢气球 解题思路
题目
题目描述
A教室的墙上挂满了五颜六色的气球,小朋友们都非常喜欢。刚一下课,小朋友们就打算去抢这些气球。每个气球在墙上都有一定的高度,只有当小朋友跳起来时,手能够到的高度大于等于气球的高度,小朋友才能摘到这个气球。为了公平起见,老师让跳的低的小朋友先摘,跳的高的小朋友后摘。小朋友都很贪心,每个小朋友在摘气球的时候都会把自己能摘的气球都摘掉。很巧的是,小朋友们跳起来手能够着的高度都不一样,这样就不会有跳起来后高度相同的小朋友之间发生争执了。
输入
第一行输入两个空格分隔的整数n,m,其中n表示小朋友的数量,m表示墙上气球的数量。第二行输入n个正整数(每两个整数之间用空格隔开),第i个数为 aiai,表示第i个小朋友跳起来手能够着的高度。
第三行输入m个正整数(每两个整数之间用空格隔开),第i个数为 hihi,表示第i个气球的高度
0<n、m≤100000,0<ai、hi≤1090<n、m≤100000,0<ai、hi≤109
输出
输出一共n行,每行一个整数。第i行表示第i个小朋友摘到的气球数量。样例输入 复制
5 6 3 7 9 6 4 1 2 3 4 5 6
样例输出 复制
3 0 0 2 1
提示
来源
思路
这道题跟普通的二分题目十分的相像,而且用普通的解法也可以解出来。但是我们在这里用二分,因为其复杂度小,不容易T。
首先这里她并没有说明数据是有序的,我们先定义一个为存储儿童身高,下标的一个结构体,在排序。
sort(a+1,a+n+1,cmp) /* 由于结构体无法直接sort,所以需要自己写一个适配函数: bool cmp(qnode A,qnode B){ return A.x<B.x; } */ sort(h+1,h+m+1);
接下来跟二分就一样了,只要一直满足
h[mid]<=a[i].x
的条件,就可以继续二分下去,最后,我们还需要恢复下标:
ans[a[i].id]=res-pre; pre=res;
代码
#include<bits/stdc++.h> using namespace std; const int maxn=100005; int n,m; struct qnode{ int x,id; }a[maxn]; int h[maxn],ans[maxn]={}; bool cmp(qnode A,qnode B){ return A.x<B.x; } int main(){ scanf(%d%d,&n,&m); for(int i=1;i<=n;i++){ scanf(%d,&a[i].x); a[i].id=i; }for(int i=1;i<=m;i++){ scanf(%d,&h[i]); }sort(a+1,a+n+1,cmp); sort(h+1,h+m+1); int le,ri,pre=0; for(int i=1;i<=n;i++){ int le=1; int ri=m; int res=0; while(le<=ri){ int mid=(le+ri)>>1; if(h[mid]<=a[i].x){ res=mid; le=mid+1; }else{ ri=mid-1; } }ans[a[i].id]=res-pre; pre=res; }for(int i=1;i<=n;i++){ printf(%d\n,ans[i]); } }
彩蛋
今天……轮到我用在线编译器了………………