Let's Play Curling(2020icpc南京站)
题目描述
输入描述
输出描述
示例
备注
思路&&感想
这道题我一开始的思路就错了,一开始就想把c求出来,可是仔细一想把c求出来一个个暴力去比较O(n^2)必然超时
在罚坐四个小时后,跟我们可爱的志愿者要了一碗鸭血粉丝汤,喝之后那思路啪的一下就上来了
在从数轴上把样例写出来之后我突然想到,让相邻的两个bule之间有尽可能的red之后就不用求c了,最后的最多的red的个数就是答案
之后开始闷头苦写,由于这可怜的代码实现能力,虽然说思路对了,但是最后还是没能写出来
AC代码
#include<iostream> #include<algorithm> #include<cstring> #include<vector> using namespace std; const int N=500010; int a[N],b[N]; int main() { int t; scanf("%d",&t); while(t--) { int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=m;i++) scanf("%d",&b[i]); sort(a+1,a+n+1),sort(b+1,b+m+1); b[m+1]=2e9,b[0]=-1e9; long long ans=0; for(int i=1;i<=m+1;i++) { int pl=upper_bound(a+1,a+n+1,b[i-1])-a; int pr=lower_bound(a+1,a+n+1,b[i])-a-1; long long sum=0; for(int j=pl;j<=pr;j++) sum++; ans=max(ans,sum); } if(ans) printf("%d\n",ans); else printf("Impossible\n"); } return 0; }
我们这隔壁队还有一种用结构体的解法
#include <bits/stdc++.h> using namespace std; int t,n,m; struct node { int nu; int ab; }a[200010]; int k,ans; bool cmp(node x,node y) { if(x.nu!=y.nu) return x.nu<y.nu; return x.ab>y.ab; } int main() { scanf("%d",&t); while(t--) { a[0].nu=0; a[0].ab=2; a[n+m+1].nu=1e9+1; a[n+m+1].ab=2; k=0; ans=0; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d", &a[i].nu); a[i].ab=1; } for(int i=n+1;i<=n+m;i++) { scanf("%d",&a[i].nu); a[i].ab=2; } sort(a+1,a+m+n+1,cmp); for(int i=1;i<=n+m;i++) { if(a[i].ab == 2){ k = 0; } else if(a[i].nu > a[i-1].nu && a[i].ab == 1){ k++; } else if(a[i].nu == a[i - 1].nu && a[i].ab == 1) { if(k == 0) continue; else k++; } ans=max(ans,k); } if(ans!=0) printf("%d\n",ans); else { printf("Impossible\n"); } } return 0; }
知识点
lower_bound( )和upper_bound( )都是利用二分查找的方法在一个排好序的数组中进行查找的。
在从小到大的排序数组中,
lower_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
upper_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
在从大到小的排序数组中,重载lower_bound()和upper_bound()
lower_bound( begin,end,num,greater<type>() ):从数组的begin位置到end-1位置二分查找第一个小于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
upper_bound( begin,end,num,greater<type>() ):从数组的begin位置到end-1位置二分查找第一个小于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
#include<bits/stdc++.h> using namespace std; const int maxn=100000+10; const int INF=2*int(1e9)+10; #define LL long long int cmd(int a,int b){ return a>b; } int main(){ int num[6]={1,2,4,7,15,34}; sort(num,num+6); //按从小到大排序 int pos1=lower_bound(num,num+6,7)-num; //返回数组中第一个大于或等于被查数的值 int pos2=upper_bound(num,num+6,7)-num; //返回数组中第一个大于被查数的值 cout<<pos1<<" "<<num[pos1]<<endl; cout<<pos2<<" "<<num[pos2]<<endl; sort(num,num+6,cmd); //按从大到小排序 int pos3=lower_bound(num,num+6,7,greater<int>())-num; //返回数组中第一个小于或等于被查数的值 int pos4=upper_bound(num,num+6,7,greater<int>())-num; //返回数组中第一个小于被查数的值 cout<<pos3<<" "<<num[pos3]<<endl; cout<<pos4<<" "<<num[pos4]<<endl; return 0; }