传送门
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了