[hdu 6012Lotus and Horticulture]优先队列
分类:stl
priority_queue
1. 题目链接
[hdu 6012Lotus and Horticulture]
2. 题意描述
中文题面: Bestcoder #91
注意:温度可以是实数。
3. 解题思路
分析题目,最终温度的答案应该只有可能是区间的左右端点、与区间左右端点距离0.5的点,这样就一定可以包括所有情况。只要将所有坐标扩大一倍,然后这些点就变成了“与区间左右端点距离1的点”。
用两个优先队列now,then分别表示覆盖当前点的区间,以及在当前点右边的区间。
坐标从0开始,向右依次枚举所有的可能的点。每次从then队列中选出一个区间左端点最靠前的,并且区间左端点在当前点的左边的点放到now队列中;然后从now 队列中选出一个区间右端点最靠前的,并且区间右端点在当前点左边的点弹出队列,每次更新答案。
复杂度:
O(nlog2n)
4. 实现代码
#include <bits/stdc++.h>
using namespace std;
typedef __int64 LL;
typedef long double LB;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
const int INF = 0x3f3f3f3f;
const LL INFL = 0x3f3f3f3f3f3f3f3fLL;
const LB eps = 1e-8;
const int MAXN = 50000 + 5;
struct Node {
LL lb, ub, a, b, c;
void p() {
printf("[%I64d %I64d %I64d %I64d %I64d]", lb, ub, a, b, c);
}
} q[MAXN];
struct cmpL {
bool operator () (const Node & x, const Node & y) const {
return x.lb > y.lb;
}
};
struct cmpR {
bool operator () (const Node & x, const Node & y) const {
return x.ub > y.ub;
}
};
LL n;
LL x[MAXN << 2], sz;
priority_queue<Node, vector<Node>, cmpR> now;
priority_queue<Node, vector<Node>, cmpL> then;
int main() {
#ifdef ___LOCAL_WONZY___
freopen("input.txt", "r", stdin);
#endif // ___LOCAL_WONZY___
int T; scanf("%d", &T);
while(T --) {
scanf("%I64d", &n);
sz = 0;
LL ans = 0, sum = 0, ansx = 0;
for(int i = 0; i < n; ++i) {
scanf("%I64d %I64d %I64d %I64d %I64d", &q[i].lb, &q[i].ub, &q[i].a, &q[i].b, &q[i].c);
q[i].lb <<= 1;
q[i].ub <<= 1;
x[sz ++] = q[i].lb - 1;
x[sz ++] = q[i].ub + 1; // 这里写成了-号,WA死我了...
x[sz ++] = q[i].lb;
x[sz ++] = q[i].ub;
sum += q[i].c; then.push(q[i]);
}
ans = sum;
sort(x, x + sz);
sz = unique(x, x + sz) - x;
Node top;
for(int i = 0; i < sz; ++i) {
while(!then.empty()) {
top = then.top();
if(top.lb > x[i]) break;
sum -= top.c;
sum += top.a;
then.pop(); now.push(top);
}
while(!now.empty()) {
top = now.top();
if(top.ub >= x[i]) break;
sum -= top.a;
sum += top.b;
now.pop();
}
if(sum > ans) {
ans = sum;
ansx = x[i];
}
}
// printf("%I64d\t", ansx);
printf("%I64d\n", ans);
}
return 0;
}