关键在把矩形框点转化为点的影响放大为矩形,此时转变为求一个点的权值最大
#include<bits/stdc++.h>
using namespace std;
#define x first
#define y second
typedef pair<int,int> PII;
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef vector<string> VS;
typedef vector<int> VI;
typedef vector<vector<int>> VVI;
vector<int> vy;
inline void divide() {sort(vy.begin(),vy.end());vy.erase(unique(vy.begin(),vy.end()),vy.end());}
inline int mp(int x) {return upper_bound(vy.begin(),vy.end(),x)-vy.begin();}
const int N = 1e4+10;
int a[N<<1];
struct info
{
ll maxn;
};
struct tag
{
ll add;
};
//处理左右子树
info operator + (const info &l,const info &r)
{
return {max(l.maxn, r.maxn)};
}
//处理节点和标记的作用
info operator + (const info &v,const tag &t)
{
return {v.maxn + t.add};
}
//处理lazy标记的传递t1作用于t2
tag operator + (const tag &t1, const tag &t2)
{
return {t1.add + t2.add};
}
struct node
{
int l,r;
info val;
tag t;
}tr[N<<4];
//settag是在pushdown里面用表示用tagt更新p点
void settag(int p,tag t)
{
//注意tag表示的是下面的区段未更新的值,settag当前p应该由t更新
tr[p].val = tr[p].val + t;
tr[p].t = t + tr[p].t;
}
void pushup(int p)
{
tr[p].val = tr[p<<1].val + tr[p<<1|1].val;
}
void pushdown(int p)
{
auto &t = tr[p].t;
if(t.add)
{
settag(p<<1,t);
settag(p<<1|1,t);
t.add = 0;
}
}
void build(int l,int r,int p)
{
tr[p].l = l, tr[p].r = r;
//初始化时用了个小trick把y上的段存到了mincnt里
if(l == r)
{
tr[p].val = {0};
return ;
}
int m = (l+r)/2;
build(l,m,p<<1);
build(m+1,r,p<<1|1);
pushup(p);
}
void update(int L,int R,tag C,int p)
{
int l = tr[p].l, r = tr[p].r;
if(L<=l&&r<=R)
{
settag(p,C);
return ;
}
pushdown(p);
int m = (l+r)/2;
if(R<=m) update(L,R,C,p<<1);
else if(L>m) update(L,R,C,p<<1|1);
else
{
update(L,m,C,p<<1);
update(m+1,R,C,p<<1|1);
}
pushup(p);
}
info query(int L,int R,int p)
{
int l = tr[p].l, r = tr[p].r;
if(L<=l&&r<=R) return tr[p].val;
pushdown(p);
int m = (l+r)/2;
if(R<=m) return query(L,R,p<<1);
else if(L>m) return query(L,R,p<<1|1);
else return query(L,m,p<<1) + query(m+1,R,p<<1|1);
}
vector<array<int,4>> event;
void solve()
{
//多测时需要把vy,evtclear
vy.clear();
event.clear();
int n,w,h;
cin>>n>>w>>h;
memset(tr,0,sizeof(node)*4*n);
//将长宽各减一使得边界计算入答案
w--, h--;
//以x轴扫描离散化y以维护线段树
for(int i=0;i<n;++i)
{
int x,y,l;
cin>>x>>y>>l;
//将一个矩形拆成两个事件
vy.push_back(y);
vy.push_back(y+h);
event.push_back({x,l,y,y+h});
//因为包括边界所以应该在x+w+1处减小
event.push_back({x+w+1,-l,y,y+h});
}
divide();
sort(event.begin(),event.end());
int m = vy.size();
build(1,m,1);
ll res = 0;
for(auto evt : event)
{
//先结算后更新
auto tmp = query(1,m,1);
res = max(res,tmp.maxn);
int y1 = mp(evt[2]), y2 = mp(evt[3]);
update(y1,y2,tag{evt[1]},1);
}
cout<<res<<'\n';
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int T = 1;
cin>>T;
while(T--)
{
solve();
}
}
标签:星星,P1502,typedef,end,int,begin,扫描线,vy,event
From: https://www.cnblogs.com/ruoye123456/p/18442816