不得不佩服出题的,,这篇情书写的真是真情实感啊→_→
→_→然而突然笔锋一转那么问题来了人都吓蠢。
感觉这题出的非常好,也是一个十分经典的一个类型。
就是如何选取一个长和宽是确定的矩形使里面的权值最大
我们想到扫描线的时候,之前做的题目都是有线段的,但是这里好像找不到扫描的线段了,一下子不知道从何下手
如果把这题稍微转换一下,,题目就会变得非常简单..
假如点P(x,y),矩形的高和宽分别是H和W
那么我就插入区间[x,x+W-1]。
这样插入表示的意义是,如果矩形的右端点落在[x,x+W-1]内,那么对于点P一定包含在矩形内部
所以,题目转换成,添加许多个区间以后,哪个点被线段覆盖的次数最多。
此时又变成我们最熟悉最经典的扫描线了~
有一个地方需要注意,那就是高度,如果超过了H,就需要把一开始的区间删除,直到新增加区间以后高度能<=H才行
所以我们可以用双端队列去维护矩形中线段的编号,以方便删除最开始的区间
#include<map>
#include<set>
#include<cmath>
#include<stack>
#include<deque>
#include<queue>
#include<cstdio>
#include<string>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define root 1,rear,1
int const MX = 4e4 + 5;
int rear;
deque<int>work;
LL A[MX], WL[MX], WR[MX];
int MAX[MX << 2], col[MX << 2];
struct Que {
int d;
int top, L, R;
Que() {}
Que(int _top, int _L, int _R, int _d) {
top = _top; L = _L; R = _R; d = _d;
}
bool operator<(const Que &b)const {
return top < b.top;
}
} Q[MX];
int BS(LL x) {
int L = 1, R = rear, m;
while(L <= R) {
m = (L + R) >> 1;
if(A[m] == x) return m;
if(A[m] > x) R = m - 1;
else L = m + 1;
}
return -1;
}
void push_up(int rt) {
MAX[rt] = max(MAX[rt << 1], MAX[rt << 1 | 1]);
}
void push_down(int rt) {
if(col[rt]) {
col[rt << 1] += col[rt];
col[rt << 1 | 1] += col[rt];
MAX[rt << 1] += col[rt];
MAX[rt << 1 | 1] += col[rt];
col[rt] = 0;
}
}
void update(int L, int R, int d, int l, int r, int rt) {
if(L <= l && r <= R) {
col[rt] += d;
MAX[rt] += d;
return;
}
int m = (l + r) >> 1;
push_down(rt);
if(L <= m) update(L, R, d, lson);
if(R > m) update(L, R, d, rson);
push_up(rt);
}
int main() {
int n, W, H;
//freopen("input.txt", "r", stdin);
while(~scanf("%d%d%d", &n, &W, &H)) {
rear = 0;
work.clear();
memset(MAX, 0, sizeof(MAX));
memset(col, 0, sizeof(col));
for(int i = 1; i <= n; i++) {
int d, y;
scanf("%I64d%I64d%d", &WL[i], &y, &d);
WR[i] = WL[i] + W - 1;
Q[i] = Que(y, 0, 0, d);
A[++rear] = WL[i];
A[++rear] = WR[i];
}
sort(A + 1, A + 1 + rear);
rear = unique(A + 1, A + 1 + rear) - A - 1;
for(int i = 1; i <= n; i++) {
Q[i].L = BS(WL[i]);
Q[i].R = BS(WR[i]);
}
sort(Q + 1, Q + 1 + n);
int ans = 0;
for(int i = 1; i <= n; i++) {
while(!work.empty() && Q[i].top - Q[work.back()].top >= H) {
int id = work.back();
work.pop_back();
update(Q[id].L, Q[id].R, -Q[id].d, root);
}
work.push_front(i);
update(Q[i].L, Q[i].R, Q[i].d, root);
ans = max(ans, MAX[1]);
}
printf("%d\n", ans);
}
return 0;
}