题目链接:
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
D1≤D2时,答案为
(
Q
2
−
Q
1
)
(Q_2-Q_1)
(Q2−Q1),而
D
1
>
D
2
D_1>D_2
D1>D2时,答案为
(
Q
2
−
Q
1
−
1
)
(Q_2-Q_1-1)
(Q2−Q1−1)。于是我们发现对于一个按照圈数升序排列的熊序列,对于每一个熊的答案为当前
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/Vmax−Q[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/Vmax−Q[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/Vmax−Q[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]×L−Q[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;
}