题解 P5835 【[USACO19DEC]Meetings会议】
出题神仙 Benq 已经说了,这题放在银组还是比较难的。
(Analysis by Benjamin Qi)
Note: This problem is quite tricky for silver!
考场上懵了,去学校之后问了 EternalAlexander 神仙,他做的,代码是我的。
思路:(时间复杂度
-
最后各头牛的坐标值,在不考虑顺序的情况下,等于没有对冲的坐标值。因为两头牛做的是对撞。
-
最后各头牛的相对顺序不变。还是因为反弹。
开始先按初始坐标从小到大排个序。
显然这题分为两步:求
-
求
T 可以二分答案。
check 函数中,根据结论 1 算出末坐标,然后记录原编号按末坐标排序,这时初坐标和末坐标就对应了。简单计算是否满足条件即可。 -
记录原编号就是用来做第二步的。
记录末坐标的数组按初坐标和末坐标大小两种方式排序,会得到两种相对顺序。这两种相对顺序应该是两个1 \dots N 的排列。树状数组求逆序对即可。
这算法很明显是对的,但我的代码通不过第二个点,比标答小 1。评论有无大佬告诉我为什么?
#include <bits/stdc++.h>
#define ll long long
#define rgi register int
#define sp putchar(32)
#define el putchar(10)
#define pb push_back
#define pii pair<int,int>
#define mkp make_pair
#define fi first
#define se second
#define filein(x) freopen(x, "r", stdin)
#define fileout(x) freopen(x, "w", stdout)
using namespace std;
const int maxn = 5e4 + 5;
int n, L, ans, sum;
struct cow {
int w, x, d;
}a[maxn];
struct tmp {
int id, y;
}b[maxn];
int c[maxn];
inline bool cmp1(cow p, cow q) { return p.x < q.x; }
inline bool cmp2(tmp p, tmp q) {
if (p.y != q.y) return p.y < q.y;
else return p.id < q.id;
}
bool check(int tim) {
for (rgi i = 1; i <= n; ++i) {
b[i].id = i;
b[i].y = a[i].x + a[i].d * tim;
}
sort(b + 1, b + n + 1, cmp2);
int tans = 0;
for (rgi i = 1; i <= n; ++i)
if (b[i].y < 0 || b[i].y > L)
tans += a[i].w;
if ((tans << 1) >= sum) return 1;
else return 0;
}
inline int lowbit(int x) { return x & (-x); }
inline void add(int i, int x) {
for (; i <= n; i += lowbit(i)) c[i] += x;
}
inline int query(int i) {
int ret = 0;
for (; i; i -= lowbit(i)) ret += c[i];
return ret;
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
filein("meetings.in"), fileout("meetings.out");
cin >> n >> L;
for (rgi i = 1; i <= n; ++i) {
b[i].id = i;
cin >> a[i].w >> a[i].x >> a[i].d;
sum += a[i].w;
}
sort(a + 1, a + n + 1, cmp1);
int l = 0, r = L;
while (l < r) {
int mid = (l + r) >> 1;
if (check(mid)) r = mid;
else l = mid + 1;
}
for (rgi i = 1; i <= n; ++i) {
add(b[i].id, 1);
ans += i - query(b[i].id);
}
cout << ans << endl;
return 0;
}