题目传送门 戳这
这道题不难发现是 (跑的快的圈数-跑的少的圈数)向下取整的总和
那么N^2算法是很显然的 怎样快点呢?
我们可以分离一下整数和小数 整数部分直接减(随便搞) 那么如果有什么 2.4-1.5 其实向下取整是一圈都没有的
所以我们对于小数部分求出逆序对再减掉就好了~
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N=100005,inf=1e9;
inline 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;
}
struct node{double x;int y,k;}p[N];
int Cmp(node x1,node x2){return x1.x<x2.x;}
int cmp(node x1,node x2){return x1.y<x2.y;}
int lb(int x){return x&(-x);}
int n,m,l,a[N],t[N];
void ins(int x){for(;x<=n;x+=lb(x))t[x]++;}
int ask(int x){int s=0;for(;x;x-=lb(x))s+=t[x]; return s;}
int main()
{
n=read(),m=read(),l=read(); int i;
for(i=1;i<=n;i++)a[i]=read();
sort(a+1,a+1+n);
LL ans=0,sum=0;
for(i=1;i<=n;i++)
{
p[i].x=(double)m*a[i]/a[n];
LL x=(LL)p[i].x;
ans+=x*(i-1)-sum,sum+=x;
p[i].x-=(double)x,p[i].y=i;
}
sort(p+1,p+1+n,Cmp);
p[1].k=1; int id=1;
for(i=2;i<=n;i++)
{
if(abs(p[i].x-p[i-1].x)>0.0000001)id++;
p[i].k=id;
}
sort(p+1,p+1+n,cmp);
for(i=n;i>0;i--)
{
ans-=ask(p[i].k-1);
ins(p[i].k);
}
printf("%lld\n",ans);
return 0;
}