题目描述
https://atcoder.jp/contests/abc274/tasks/abc274_f
输入样例
3 10
100 0 100
1 10 30
10 20 10
输出样例
111
算法
(贪心+暴力) O ( n 2 ) O(n^2) O(n2)
首先有一点很重要,那就是最大值的区间左端点一定有鱼
那样的话我们就可以枚举所有点为左端点,求在
[
A
,
A
+
X
]
[A, A+X]
[A,A+X] 区间内质量的最大值
那么这个最大值怎么求呢,在这里我们可以计算时间
什么时间呢?
那就是其余所有鱼在区间内的时间
左端点的鱼走过的路程
s
1
=
x
1
+
t
∗
v
1
s_1 = x_1 + t * v_1
s1=x1+t∗v1
其余所有鱼走过的路程
s
2
=
x
2
+
t
∗
v
2
s_2 = x_2 + t * v_2
s2=x2+t∗v2
计算可得
△
s
=
x
2
−
x
1
+
t
∗
(
v
2
−
v
1
)
\triangle s = x_2 - x_1 + t * (v_2-v_1)
△s=x2−x1+t∗(v2−v1)
△
s
∈
[
0
,
X
]
\triangle s \in [0, X]
△s∈[0,X]
计算可得
t
∈
[
x
1
−
x
2
v
2
−
v
1
,
X
+
x
1
+
x
2
v
2
−
v
1
]
t \in [{x_1 - x_2 \over v_2 - v_1}, {X + x_1 + x_2 \over v_2 - v_1}]
t∈[v2−v1x1−x2,v2−v1X+x1+x2]
已经知道时间范围了,接下来就简单多了
还需要有几个特别注意的地方
1.
当
v
1
=
v
2
v_1 = v_2
v1=v2 的时候分母为0,需要单独讨论
当
v
1
=
v
2
v_1 = v_2
v1=v2 那就是说明相对速度为
0
0
0 ,只需要讨论在
0
0
0 时刻是否符合条件就可以啦
2.
关于
d
o
u
b
l
e
double
double 类型的区间覆盖问题
对于
i
n
t
int
int 类型我们的方式就是
s[l] += a;
s[r+1] -= a;
这里的
l
l
l 表示左端点,是不会改变的,会改变的是
r
+
1
r+1
r+1 ,
r
+
1
r+1
r+1 表示的是从
r
r
r 之后的第一个点开始所有的点全部都要减去
a
a
a
关于
d
o
u
b
l
e
double
double 类型,
r
r
r 后面是什么呢,在这里我们可以设置一个
e
p
s
=
1
e
−
9
eps = 1e-9
eps=1e−9, 那么
r
r
r 的后一个位置就是
r
+
e
p
s
r+eps
r+eps ,就变成了下面这个样子
s[l] += a;
s[r+eps] -= a;
C++ 代码
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<unordered_map>
#include<unordered_set>
#include<cmath>
#include<map>
#include<set>
#include<stack>
#include<vector>
#include<deque>
#include<cmath>
#include<ctime>
#include<cfloat>
using namespace std;
const int N=2010;
const double eps=1e-9;
typedef long long ll;
int a[N],x[N],v[N],w[N];
map<double,int> mp;
int main()
{
int n,X;
cin>>n>>X;
int ans=0;
for(int i=1;i<=n;i++) scanf("%d %d %d",&w[i],&x[i],&v[i]);
for(int i=1;i<=n;i++)//枚举左端点
{
mp.clear();
int p=w[i];
for(int j=1;j<=n;j++)
{
if(i==j) continue;
if(v[j]==v[i])//相对速度为0 只用看0时刻就可以啦
{
if(x[j]>=x[i]&&x[j]<=x[i]+X)
{
p+=w[j];
continue;
}
}
double l=1.0*(x[i]-x[j])/(v[j]-v[i]);
double r=1.0*(X+x[i]-x[j])/(v[j]-v[i]);
if(l>=r) swap(l,r);
if(r>=0)
{
l=max(l,0.0);
mp[l]+=w[j];
mp[r+eps]-=w[j];
}
}
int tmp=p;
for(auto [t,ww]:mp)
{
p+=ww;
tmp=max(tmp,p);
}
ans=max(ans,tmp);
}
cout<<ans<<endl;
}