超级跳棋

ISIJ 2018 超级跳棋(Training Round D6T5)

题目描述

小明是今年超级跳棋比赛的裁判,每轮有三名选手参加,结束时统计的分数一定是正整数,形如 a:b:c。小明的任务是在一块特殊的计分板上展示分数,他一共准备了 n 块写有正整数 x 1 x 2 x n 的卡片,可供填写在 a、b、c 的位置上。此外,小明了解到超级跳棋的规则,他发现 a、b、c 之间最多相差 k 倍,例如 c a > k 就是不合法的分数。为了检验他准备得是否充分,你需要计算小明可以在计分板上摆放出多少种不同的分数,即 (a,b,c) 这样的三元组有多少个。

限制

1s 256M

对于 20% 的数据, 3 n 100 , 000 k = 1 1 x i 100 , 000

对于另外 20% 的数据, 3 n 100 1 k 100 1 x i 100

对于另外 30% 的数据, 3 n 100 , 000 1 k x i 10 9 x i

对于另外 30% 的数据, 3 n 100 , 000 1 k x i 10 9

输入格式

第一行,两个整数 n k

第二行, n 个整数 x 1 x 2 x n

输出格式

一个整数,表示 (a,b,c) 三元组的个数

输入样例

5 2

1 1 2 2 3

输出格式

9

样例解释

小明可以摆出的 a:b:c 有以下这些:1:1:2、1:2:1、2:1:1、1:2:2、2:1:2、2:2:1、2:2:3、2:3:2、3:2:2。由于 k = 2 ,1 和 3 不能同时出现。

题解

首先将 x i 排序,对于固定的最小值 x i ,a、b、c 三个数必然在 x i x j 中选(即 x j + 1 x i > k ),当然对于 i 可以扫描线快速求得 j 。假设 x i 必然取,然后可以根据 x i 选 1 个还是 2 个还是 3 个,分类讨论并用乘法原理统计答案。需要同时维护当前 x i x j 有几个是只出现了 1 次、有几个是出现了至少 2 次的(用 map 记录一个数出现了几次)。

这道题很睿智,不知道为什么放在第三题

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int read(){
    int x=0,f=1; char ch=getchar();
    while (ch<'0'||ch>'9'){if (ch=='-') f=-1; ch=getchar();}
    while (ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}
int a[100005],b[100005],d[100005],p,k,n;
int s[100005];
ll ans=0;
int find(int x){
    int l=1,r=p,ans=-1;
    ll q=(ll)x*k;
    while (l<=r){
        int mid=(l+r)>>1;
        if (d[mid]<=q){ l=mid+1; ans=mid;} else r=mid-1;
    }
    return ans;
}
int main(){
    n=read(),k=read();
    for (int i=1;i<=n;i++)
    a[i]=read();
    sort(a+1,a+1+n);
    for (int i=1;i<=n;i++){
        if (a[i]!=a[i-1]) p++,d[p]=a[i];
        b[p]++;
    }
    for (int i=1;i<=p;i++){
        if (b[i]>=2) s[i]=s[i-1]+1;
        else s[i]=s[i-1]; 
    }
    for (int i=1;i<=p;i++){
        int q1=find(d[i]);
        if (q1==-1||q1<i) continue;
        int kd=q1-i;
        ans+=1ll*kd*(kd-1)*3;
        ans+=1ll*(s[q1]-s[i])*3;
        if (b[i]>=2) ans+=1ll*kd*3;
        if (b[i]>=3) ans++;
    }
    cout<<ans<<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/beautiful_CXW/article/details/81743317