ACM ArabellaCPC 2015 E题.二分or离散化

传送门:https://odzkskevi.qnssl.com/1110bec98ca57b5ce6aec79b210d2849?v=1492616502 

题意:找到相差小于32的两个数,i<j,问有多少对,肯定有超市,所以要有优化方案。


二分:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int maxn=10000+5;
int a[maxn];

int main()
{
    //freopen("in.txt","r",stdin);
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n;
        int cnt=0;
        scanf("%d",&n);
        for(int i=0;i<n;i++)
            scanf("%d",&a[i]);
        sort(a,a+n);
        for(int i=0;i<n;i++)
        {
            int target=a[i]+32;
            if(a[n-1]<target)
            {
                cnt+=n-i-1;
                continue;
            }
            int left=i+1,right=n-1,mid;
            while(1)
            {
                mid=(left+right)/2;
                if(target>a[mid-1] && target<=a[mid])
                    break;
                if(a[mid]<target)
                    left=mid+1;
                else
                    right=mid;
            }
            cnt+=mid-i-1;
        }
        printf("%d\n",cnt);
    }
    return 0;
}

这个是其他人的思路,我觉得比较好,用到了点离散化的思想

#include <bits/stdc++.h>

using namespace std;
const int maxn = 10000+10;
int v[maxn];
int s[maxn];
int q[maxn];
typedef long long LL;
LL ans;
int main()
{
//    freopen("in.txt","r",stdin);
    int t,n,a,cnt;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);

        for(int i = 0; i<n; i++)
        {
            scanf("%d",&q[i]);
        }

        sort(q,q+n);

        cnt = 0;
        a = 0;
        for(int i = 0; i<n; i++)
        {
            if(q[i]!=a)
            {
                cnt++;
                v[cnt] = q[i];
                s[cnt] = 1;
                a = q[i];
            }
            else s[cnt]++;
        }

        ans = 0;
        for(int i = 1; i<cnt; i++)//与其他数
        {
            for(int j = i+1; j<=cnt; j++)
            {
                if(abs(v[i]-v[j])<32)
                    ans += s[i]*s[j];

                else break;//因为已经排了序,如果与前面的差值都>=32, 那么与后面的差值就更大,直接退出即可。
            }
        }

        for(int i = 1; i<=cnt; i++)//与相同的自己,i<j,2个则2*1/2=1,三个则3*2/2=3个,1个就没了
            ans += s[i]*(s[i]-1)/2;

        printf("%lld\n",ans);

    }
    return 0;
}



posted @ 2017-04-22 22:37  Lawliet__zmz  阅读(193)  评论(0编辑  收藏  举报