【NOIP2012模拟8.6】绕圈跑

这题考场刚了很久,最后没想到正解,只好打了个n2暴力。
后来发现正解很容易理解,就开打了。
1h。。。
2h。。。
3h。。。
精度问题坑了我很久[○・`Д´・ ○]
没想到的是:

反正都要离散化,为什么不将它全部都乘一个最大速度呢???

WDF!!!

好了,一改,就切了。。。o ( ╥ ﹏ ╥ ) o
上标:

#include<cstdio>
#include<algorithm>
#define N 100010
#define db long double
#define ll long long
using namespace std;
struct node{int fr,re;}b[N];
int n,l,c,a[N],id[N],t[N<<3],tot=0;
ll ans=0,sum=0,q;
db time;

inline int read()
{
	int x=0; char c=getchar();
	while (c<'0' || c>'9') c=getchar();
	while (c>='0' && c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
	return x;
}

int cmp(node x,node y) {return x.re<y.re;}

void insert(int x,int l,int r,int ins)
{
	t[x]++;
	if (l==r) return;
	int mid=l+r>>1;
	if (ins<=mid) insert(x<<1,l,mid,ins);
	else insert(x<<1|1,mid+1,r,ins);
}

int total(int x,int l,int r,int fl,int fr)
{
	if (fl==l && fr==r) return t[x];
	int mid=l+r>>1;
	if (fr<=mid) return total(x<<1,l,mid,fl,fr);
	else if (fl>mid) return total(x<<1|1,mid+1,r,fl,fr);
	else return total(x<<1,l,mid,fl,mid)+total(x<<1|1,mid+1,r,mid+1,fr);
}

int main()
{
	freopen("circle.in","r",stdin);
	freopen("circle.out","w",stdout);
	n=read(),l=read(),c=read();
	for (int i=1;i<=n;i++) a[i]=read();
	sort(a+1,a+n+1);time=1.0*l*c/a[n];
	for (int i=1;i<=n;i++)
	{
		q=a[i]*time/c;
		b[i].re=a[i]*l-q*a[n];
		b[i].fr=i;
	}
	sort(b+1,b+n+1,cmp);
	for (int i=1;i<=n;i++)
	{
		id[b[i].fr]=++tot;
		while (b[i].re==b[i+1].re) id[b[++i].fr]=tot;
	}
	for (int i=1;i<=n;i++)
	{
		q=a[i]*time/c;
		ans+=(i-1)*(q-1)-sum;
		ans+=total(1,1,tot,1,id[i]);
		insert(1,1,tot,id[i]);
		sum+=q;
	}
	printf("%lld\n",ans);
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值