luoguP4670[BalticOI 2011 Day2]Plagiarism题解

传送门
Description
世界编程大赛的选手们提交N份程序文件f1, …, fN给评测系统。在将评测结果正式公布之前,评委会想要排除一切可能的剽窃现象。他们已有一个对比程序,用来比较两份程序文件,并判断它们是否太过相似了。 然而程序文件的数目相当大,把每两份(一对,pair)文件都进行比较的话将花太多的时间。另一方面,许多对(pair)可以直接被排除,如果文件的大小相差太大的话。 更准确地说,评委会决定,如果每两份文件(一对,pair)中,较小文件的体积小于较大文件的体积的90%,那将直接不比较这样的一对(pair)。所以,对比程序只比较这样的一对(fi, fj): i≠j, size(fi )≤ size(fj )且size(fi )≥0.9∙size(fj )。 编写程序计算有多少对(pair)文件需要被比较。
Input:
第1行包含一个整数N,即提交的程序文件总数。 第2行包含N个整数size(f1), …, size(fN),每个整数代表文件的体积大小。
Output:
第1行,也是唯一的一行,给出一个整数,即需要被比较的文件的对(pair)的数目。
看到这道题,我们首先得想法就是用\(n^2\)的暴力算法,从\(i\)\(j\)进行暴力枚举,具体代码如下:

#include<algorithm>
#include<iostream>
#include<cstdio>
using namespace std;
int n;
int a[10000003];
int ans;
int read() {
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9') {
        if(ch=='-') f=-f;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9') {
        x=x*10+ch-'0';
        ch=getchar();
    }
    return x*f;
}
int main() {
    n=read();
    for(int i=1;i<=n;i++) a[i]=read();
    sort(a+1,a+n+1);
    for(int i=1;i<n;i++) {
        for(int j=i+1;j<=n;j++) {
            if(a[i]>=0.9*a[j]) ans++;
        }
    }
    cout<<ans;
}

显然,这种达到\(O(n^2)\)的算法是不满足题目要求\(1≤N≤10^5\)的,所以我们又想出了一种新的方法:在(a[i]<0.9*a[j])之后,\(return\)

#include<algorithm>
#include<iostream>
#include<cstdio>
using namespace std;
int n;
int a[10000003];
int ans;
int read() {
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9') {
        if(ch=='-') f=-f;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9') {
        x=x*10+ch-'0';
        ch=getchar();
    }
    return x*f;
}
int main() {
    n=read();
    for(int i=1;i<=n;i++) a[i]=read();
    sort(a+1,a+n+1);
    for(int i=1;i<n;i++) {
        for(int j=i+1;j<=n;j++) {
            if(a[i]>=0.9*a[j]) ans++;
            else break;
        }
    }
    cout<<ans;
}

但是,在吸氧之后,这程序依然只能拿\(70\),于是,我们想到了一个代替\(for\)的方法:二分

#include<algorithm>
#include<iostream>
#include<cstdio>
using namespace std;
int n;
int a[1000003];
long long ans;
int read() {
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9') {
        if(ch=='-') f=-f;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9') {
        x=x*10+ch-'0';
        ch=getchar();
    }
    return x*f;
}

int erfen(int i,int l,int r) {
    while(l<=r) {
    int mid=(l+r)/2;
    if(a[i]>=0.9*a[mid]) l=mid+1;
    if(a[i]<0.9*a[mid]) r=mid-1;
    }
    return l;
}
int main() {
    n=read();
    for(int i=1;i<=n;i++) a[i]=read();
    sort(a+1,a+n+1);
    for(int i=1;i<n;i++) {
        ans+=erfen(i,i,n)-i-1;
    }
    cout<<ans;
}

这样就可以A了

posted @ 2019-04-26 16:10  zeroqq  阅读(215)  评论(0编辑  收藏  举报
Live2D