题目背景
小卡买到了一套新房子,他十分的高兴,在房间里转来转去。
题目描述
晚上,小卡从阳台望出去,“哇~~~~好多星星啊”,但他还没给其他房间设一个窗户。
天真的小卡总是希望能够在晚上能看到最多最亮的星星,但是窗子的大小是固定的,边也必须和地面平行。
这时小卡使用了超能力(透视术)知道了墙后面每个星星的位置和亮度,但是小卡发动超能力后就很疲劳,只好拜托你告诉他最多能够有总和多亮的星星能出现在窗口上。
输入格式
本题有多组数据,第一行为 TT,表示有 TT 组数据。
对于每组数据:
第一行 33 个整数 n,W,Hn,W,H 表示有 nn 颗星星,窗口宽为 WW,高为 HH。
接下来 nn 行,每行三个整数 x_i,y_i,l_ixi,yi,li 表示星星的坐标在 (x_i,y_i)(xi,yi),亮度为 l_ili。
输出格式
TT 个整数,表示每组数据中窗口星星亮度总和的最大值。
输入输出样例
输入 #1复制
2 3 5 4 1 2 3 2 3 2 6 3 1 3 5 4 1 2 3 2 3 2 5 3 1
输出 #1复制
5 6
说明/提示
小卡买的窗户框是金属做的,所以在边框上的不算在内。
数据范围
1\le T \le 101≤T≤10
1\le n \le 10^41≤n≤104
1\le W,H \le 10^61≤W,H≤106 0\le x_i,y_i < 2^{31}0≤xi,yi<231
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 20010;
struct Segment_Tree{
struct info{ //线段树数组
int l,r;
ll mx,plz; //mx表示最大值 plz为懒标记
}node[MAXN << 2];
void Build(int n,int l,int r) // 先建空树 以y为轴
{
node[n].l = l,node[n].r = r;
if(node[n].l == node[n].r){
return;
}
int mid = (l+r) >> 1,lt = n << 1,rt = n << 1|1;
Build(lt,l,mid);Build(rt,mid+1,r);
return;
}
void push_down(int n) //懒标记
{
if(node[n].plz){
int lt = n << 1,rt = n << 1|1;
node[lt].mx += node[n].plz;
node[rt].mx += node[n].plz;
node[lt].plz += node[n].plz;
node[rt].plz += node[n].plz;
node[n].plz = 0;
}
return;
}
void modify(int n,int l,int r,int k) //区间修改
{
if(node[n].l >= l && node[n].r <= r){
node[n].plz += k;
node[n].mx += k;
return;
}
push_down(n);
int lt = n << 1,rt = n << 1|1;
if(node[lt].r >= l) modify(lt,l,r,k);
if(node[rt].l <= r) modify(rt,l,r,k);
node[n].mx = max(node[lt].mx,node[rt].mx); //维护最大值
return;
}
}ST;
int num[MAXN];
struct in{
int l,r,h,v; //对h的值按小到大排序 h相同时按v的正负排 因为对两边重合时要先入边再出边
bool operator < (const in &a) const{ return h == a.h ? v > a.v : h < a.h;}
}start[MAXN];
void lsh(int n) // 离散化操作
{
sort(start+1,start+n+1);
sort(num+1,num+n+1);
int cnt = unique(num+1,num+n+1) - num - 1;
for(int i = 1; i <= n; i++){
int pos1 = lower_bound(num+1,num+cnt+1,start[i].l) - num;
int pos2 = lower_bound(num+1,num+cnt+1,start[i].r) - num;
start[i].l = pos1;
start[i].r = pos2;
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--){
int x,y,l,n,w,h;
scanf("%d %d %d",&n,&w,&h);
for(int i = 1;i <= n; i++){
scanf("%d %d %d",&x,&y,&l);
num[(i << 1) - 1] = y;
num[i << 1] = y+h-1;
start[(i << 1) - 1] = (in) {y,y+h-1,x,l};
start[i << 1] = (in) {y,y+h-1,x+w-1,-l};
}
n <<= 1; // 每个点有两条边
lsh(n);
ST.Build(1,1,n);
ll ans = 0;
for(int i = 1;i <= n; i++){
ST.modify(1,start[i].l,start[i].r,start[i].v); //从小到大扫描
ans = max(ans,ST.node[1].mx); // 记录最大值
}
printf("%lld\n",ans);
}
return 0;
}