首页 > 其他分享 >P1502 窗口的星星(扫描线)

P1502 窗口的星星(扫描线)

时间:2024-10-01 12:33:22浏览次数:6  
标签:星星 P1502 typedef end int begin 扫描线 vy event

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

#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

相关文章

  • 扫描线-学习笔记
    扫描线-学习笔记引言:扫描线算法用于解决给出多个矩形组成的图形求解其面积、周长等问题。时间复杂度常见为\(O(n\log_2^n)\)级别,空间复杂度略大于\(O(n)\),属于线段树的一种运用。一、求面积题目:P5490【模板】扫描线&矩形面积并求\(n\)个四边平行于坐标轴的矩形的面积......
  • matlab获取STK中卫星星座TLE数据信息
    笔者因课题需求,在STK构建了Starlink一期一阶段共1584颗卫星的LEO卫星星座。想要导出TLE信息,但STK手动导出太麻烦,因此萌生用代码解决的念头。通过查阅相关资料,利用matlab与STK互联的方法,获取STK场景中所构建的卫星TLE。Matlab代码如下:clear;clc;%打开STK软件uiapplication......
  • 扫描线
    include<bits/stdc++.h>usingnamespacestd;definepiipair<int,int>definemkpmake_pairdefinepbpush_backdefinemid((l+r)>>1)definels(x)(x<<1)definers(x)((x<<1)+1)defineLLlonglongdefineintlonglongconstin......
  • 扫描线总结
    引入面积并(周长并)如下图给你一堆矩形求它的面积并或周长并。显然直接做,就是考虑容斥,但明显不好做。那就思考如何切割或补,显然补完要减的图形也不规整,只能考虑割。如何将其割成规整的图形,明显矩形最容易计算和割。把它割成矩形后发现,每次遇到某个矩形的边就会变,所以考虑一条......
  • 扫描线
    引入扫描线一般运用在图形上面,它和它的字面意思十分相似,就是一条线在整个图上扫来扫去,它一般被用来解决图形面积,周长,以及二维数点等问题。Atlantis问题题意在二维坐标系上,给出多个矩形的左下以及右上坐标,求出所有矩形构成的图形的面积。解法根据图片可知总面积可以直接暴力......
  • 扫描线
    扫描线经典问题之求矩形面积并,可以使用线段树和扫描线。比方说我们要对这俩东西求面积并,我们简单分割一下。然后扫描线就是,从最下面一条绿线向上扫过去,遇到下底边则加上这个矩形,遇到上底边则减去这个矩形。回到这道题,发现给了我们矩形的两个角,那么上底边和下底边是好求的。......
  • 扫描线总结
    扫描线是线段树的典型应用。这玩意不难,用途也比较狭窄,重点在理解思想。例0【模板】扫描线题意求\(n\)个四边平行于坐标轴的矩形的面积并。对于\(100\%\)的数据,\(1\len\le{10}^5\),\(0\lex_1<x_2\le{10}^9\),\(0\ley_1<y_2\le{10}^9\)。解析如果用暴力......
  • 走进 “星星的孩子” 的世界:理解与关爱儿童自闭症
    在这个充满生机与活力的世界里,有一群特殊的孩子,他们仿佛来自遥远的星球,沉浸在自己的独特世界中,难以与外界进行有效的沟通和互动。他们是自闭症儿童,也被称为“星星的孩子”。自闭症,又称孤独症谱系障碍,是一种广泛性发育障碍。这些孩子在社交互动、语言沟通、兴趣和行为方面存在......
  • 刍议线段树 3 (扫描线)
    扫描线扫描线是一种另外的思想,只是其中会运用到线段树以求优化。所以不要将扫描线简单的并为线段树的一个小拓展。例题:https://www.luogu.com.cn/problem/P5490大意:求\(n\)个四边平行于坐标轴的矩形的面积并。思路:纵向分割图形我们考虑把这些纵向矩形分割。那么,总面积就......
  • P1502 窗口的星星 题解
    题目传送门。思路扫描线扫描线首先,将题目中给出的条件和问题进行转化:首先先不考虑边框上的点不算在内的限制,考虑一个点可以对那些矩形产生贡献。只考虑矩形的右上角,容易发现,每个星星的亮度只对右上角在以星星为左下角的长为\(W\),高为\(H\)的矩形有贡献。如图。那么便可......