评测记录:https://atcoder.jp/contests/abc274/submissions/35955376
思路:每次枚举一条鱼 i,计算出其他每条鱼进入 [xi,xi+A] 区间的时间段;然后从小往大枚举每个时间段端点,如果是左端点则+该时间段代表的鱼权值,右端点则减掉,过程中取最大值
考虑了多个端点同时刻的情况,方案是先加后减
求助为什么还是wa
const int N = 2010;
ll a, w[N], x[N], v[N], mx;
int n;
struct frac{
int x, y;
};
vector<pair<frac, int> > p;
bool cmp(pair<frac, int> a, pair<frac, int> b){
if(a.first.x * b.first.y == a.first.y * b.first.x){
return a.second > b.second;
}
return a.first.x * b.first.y < a.first.y * b.first.x;
}
frac mkfrac(ll u, ll d){
frac res;
res.x = u;
res.y = d;
return res;
}
void solve(){
n = rdi;
a = rdll;
for(int i = 1; i <= n; ++ i){
w[i] = rdll;
x[i] = rdll;
v[i] = rdll;
}
for(int i = 1; i <= n; ++ i){
while(p.size()){
p.pop_back();
}
for(int j = 1; j <= n; ++ j){
if(j == i){
continue;
}
#define pb push_back
#define mp make_pair
if(x[j] > x[i] + a){
if(v[j] < v[i]){
p.pb(mp(mkfrac(x[j]-x[i]-a, v[i]-v[j]), j));
p.pb(mp(mkfrac(x[j]-x[i], v[i]-v[j]), -j));
}
} else if(x[j] >= x[i]){
p.pb(mp(mkfrac(0, 1), j));
if(v[j] < v[i]){
p.pb(mp(mkfrac(x[j]-x[i], v[i]-v[j]), -j));
} else if(v[j] == v[i]){
p.pb(mp(mkfrac(1, 0), -j));
} else {
p.pb(mp(mkfrac(x[i]+a-x[j], v[i]-v[j]), -j));
}
} else {
if(v[j] > v[i]){
p.pb(mp(mkfrac(x[i]-x[j], v[j]-v[i]), j));
p.pb(mp(mkfrac(x[i]+a-x[j], v[j]-v[i]), -j));
}
}
}
sort(p.begin(), p.end(), cmp);
ll ans = w[i];
mx = max(mx, ans);
for(int j = 0; j < p.size(); ++ j){
if(p[j].second < 0){
ans -= w[-p[j].second];
} else {
ans += w[p[j].second];
}
mx = max(mx, ans);
}
}
writen(mx);
}