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;    
} 

 

posted @ 2020-12-20 20:39  TheWeak  阅读(154)  评论(0编辑  收藏  举报