关键在把矩形框点转化为点的影响放大为矩形,此时转变为求一个点的权值最大

#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();
	}
}
 posted on 2024-10-01 12:37  ruoye123456  阅读(16)  评论(0)    收藏  举报