思考熊的马拉松——解题报告

题目链接:

http://120.79.19.114:666/problem/153
题目描述
在这里插入图片描述

题目分析:

1.首先我们可以很自然的把熊跑的路程分为两个部分,一个是整数圈部分,一个是不足一圈的部分。
2.然后我们发现如果不考虑不足一圈的部分,只要圈数小于当前圈数都将被套圈,而次数就是圈数之差的绝对值。
3.然后再来考虑不足一圈的部分,举个例子,用 Q Q Q表示圈数, D D D表示不足一圈的路程,有两个熊 Q 1 , D 1 , Q 2 , D 2 ( Q 1 < Q 2 ) Q_1,D_1,Q_2,D_2(Q_1<Q_2) Q1,D1,Q2,D2(Q1<Q2)。我们很容易得到一个结论, D 1 ≤ D 2 D_1 \leq D_2 D1D2时,答案为 ( Q 2 − Q 1 ) (Q_2-Q_1) (Q2Q1),而 D 1 > D 2 D_1>D_2 D1>D2时,答案为 ( Q 2 − Q 1 − 1 ) (Q_2-Q_1-1) (Q2Q11)。于是我们发现对于一个按照圈数升序排列的熊序列,对于每一个熊的答案为当前 Q n o w Q_{now} Qnow和前面 Q p r e Q_{pre} Qpre之差的和减去关于 ( D p r e , D n o w ) (D_{pre},D_{now}) (Dpre,Dnow)的逆序对数。

坑爹的实现部分:

由于坑爹的精度问题,我们需要避免使用 d o u b l e double double,一次来消除精度误差。下面是推导过程:
T = A × L / V m a x T=A \times L/V_{max} T=A×L/Vmax
d i s t [ i ] = V [ i ] × T dist[i]=V[i] \times T dist[i]=V[i]×T
Q [ i ] = ⌊ d i s t [ i ] A ⌋ Q[i]=\lfloor \frac{dist[i]}{A} \rfloor Q[i]=Adist[i]
所以: Q [ i ] = ⌊ V [ i ] × T A ⌋ = V [ i ] × A × L / ( A × V m a x ) = V [ i ] × L / V m a x Q[i]=\lfloor \frac{V[i] \times T}{A}\rfloor=V[i] \times A \times L/(A \times Vmax)=V[i] \times L/Vmax Q[i]=AV[i]×T=V[i]×A×L/(A×Vmax)=V[i]×L/Vmax
D [ i ] = d i s t [ i ] − Q [ i ] × A = V [ i ] × A × L / V m a x − Q [ i ] × A D[i]=dist[i]-Q[i] \times A=V[i] \times A \times L/Vmax-Q[i] \times A D[i]=dist[i]Q[i]×A=V[i]×A×L/VmaxQ[i]×A
因为求逆序对时,只考虑相对大小,与具体值无关,所以可以直接去掉不影响相对大小的A:
D [ i ] = d i s t [ i ] − Q [ i ] × A = V [ i ] × L / V m a x − Q [ i ] D[i]=dist[i]-Q[i] \times A=V[i] \times L/Vmax-Q[i] D[i]=dist[i]Q[i]×A=V[i]×L/VmaxQ[i]
通分: D [ i ] = d i s t [ i ] − Q [ i ] × A = V [ i ] × L / V m a x − Q [ i ] × V m a x / V m a x D[i]=dist[i]-Q[i] \times A=V[i] \times L/Vmax-Q[i] \times Vmax/V_{max} D[i]=dist[i]Q[i]×A=V[i]×L/VmaxQ[i]×Vmax/Vmax
同上去掉不影响答案的 V m a x V_{max} Vmax,得到: D [ i ] = d i s t [ i ] − Q [ i ] × A = V [ i ] × L − Q [ i ] × V m a x D[i]=dist[i]-Q[i] \times A=V[i] \times L-Q[i] \times V_{max} D[i]=dist[i]Q[i]×A=V[i]×LQ[i]×Vmax。到此,完美解决了 d o u b l e double double的精度问题,只需要 l o n g   l o n g long\ long long long就能解决一切问题。
正解程序

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#include <cmath>
#define eps 1e-6

using namespace std;
typedef long long ll;
const ll maxn=100010;
ll v[maxn],quan[maxn],pre[maxn],tree[maxn];
ll n,m,A,L;
ll dist[maxn],temp[maxn];
map<double,ll> mp;
ll lowbit(ll x)
{
	return x&(-x);
}
void change(ll x)
{
	for(ll i=x;i<=m;i+=lowbit(i))
		tree[i]++;
}
ll getans(ll x)
{
	ll res=0;
	for(ll i=x;i;i-=lowbit(i))
		res+=tree[i];
	return res;
}
int main()
{
	//freopen("test.txt","r",stdin);
	ll T,C;
	scanf("%lld%lld",&T,&C);
	while(T--)
	{
		mp.clear();
		memset(tree,0,sizeof(tree));
		scanf("%lld%lld%lld",&n,&A,&L);
		for(ll i=1;i<=n;i++)
			scanf("%lld",&v[i]);
		sort(v+1,v+1+n);
		double t=A*L/(double)v[n];
		for(ll i=1;i<=n;i++)
		{
			quan[i]=v[i]*L/v[n];
			temp[i]=dist[i]=v[i]*L-quan[i]*v[n];
			pre[i]=pre[i-1]+quan[i];
		}
		sort(temp+1,temp+1+n);
		m=unique(temp+1,temp+1+n)-temp-1;
		for(ll i=1;i<=m;i++)
			mp[temp[i]]=i;
		ll ans=0;
		for(ll i=1;i<=n;i++)
		{
			change(mp[dist[i]]);
			ll times=getans(m)-getans(mp[dist[i]]);
			ll pos=lower_bound(quan+1,quan+1+n,quan[i])-quan;
			pos--;
			ans+=quan[i]*pos-pre[pos]-times;
		}
		printf("%lld\n",ans);
	}
	
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值