写个暴力法O(n^3)竟然过了,数据有点水。暴力法虽然不好,但是可以帮助我们理解:
#include<bits/stdc++.h>
using namespace std;
const int N=1e8+10;
int a[N];
int n,ans;
int main()
{
cin>>n;
for(int i=0;i<n;i++)
{
cin>>a[i];
}
sort(a,a+n);
for(int x=0;x<n;x++)
{
for(int y=x+1;y<n;y++)
{
for(int z=y+1;z<n;z++)
{
int xy=a[y]-a[x];
int yz=a[z]-a[y];
if(yz>=xy&&yz<=2*xy)
{
ans++;
}
}
}
}
cout<<ans;
return 0;
}
题目说了:
ok,现在我们从点的角度来看:
ok,这道题的数据范围是,我们可以枚举x,y这两个点,也就是,也就是,第三个点z我们可以在上面求出来的z的范围里去,里有多少个点,就说明有多少个合法的z。
第三个点的复杂度我们要控制在 ,这样的话整体的复杂度是
那么现在我们的问题就是求怎么找到,观察下图我们发现我们可以将问题转变为求:
大于等于2y-x的最大的点
小于等于3y-2x的最大的点
#include<bits/stdc++.h>
using namespace std;
const int N=1010;
int ans,n;
int a[N];
int main()
{
cin >>n;
for(int i=0;i<n;i++)cin>>a[i];
sort(a,a+n);
for(int i=0;i+2<n;i++) //给j,z留空
{
for(int j=i+1,l=i+1,r=i+1;j+1<n;j++) //j+1<n是为了给z留空
{
while(l<n&&a[l]-a[j]<a[j]-a[i])l++; //xy<=yz
while(r<n&&a[r]-a[j]<=2*(a[j]-a[i]))r++; //yz<=2(xy)
ans+=r-l; //[L,R]之间的就是z的所有合法可取点,全部加上
}
}
cout<<ans<<endl;
return 0;
}