社区讨论

题解来了

P5873 [SEERC2018] Points and Rectangles参与者 10已保存回复 10

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
10 条
当前快照
1 份
快照标识符
@lo2vulp3
此快照首次捕获于
2023/10/23 20:37
2 年前
此快照最后确认于
2023/10/23 20:37
2 年前
查看原帖
C
#include <bits/stdc++.h>
using namespace std;
const int N = 5e5 + 5;
typedef long long ll;
struct event{
	int tp;
	int x,y;
	int a1,b1,a2,b2;
	event(){}
	event(const int _x,const int _y):
	x(_x),y(_y){ tp = 1;}
	event(const int _a1,const int _b1,const int _a2,const int _b2):
	a1(_a1),b1(_b1),a2(_a2),b2(_b2){tp = 2;}
};
event Q[N];
ll ans[N];
int n;
int valy[N*3],leny=0;
#define idx(x) (lower_bound(valy+1,valy+leny+1,(x))-valy)
struct line{
	int x,l,r,tp,id;
	line(){}
	line(const int _x,const int _l,const int _r,const int _tp,const int _id):
	x(_x),l(_l),r(_r),tp(_tp),id(_id){}
};
int tr[N*3];
#define lowbit(x) (x&(-x))
inline void upd(int x,int v) { ++x;for(int i=x;i<=leny+1;i+=lowbit(i)) tr[i] += v;}
inline int Sum(int x) {++x;int res = 0;for(int i=x;i;i^=lowbit(i)) res += tr[i];return res;}
inline int Qry(int l,int r) { return Sum(r)-Sum(l-1);}
inline void inc(int l,int r,int v) { upd(l,v);upd(r+1,-v);}
inline bool cmp1(const line &a,const line &b)
{
	if(a.x != b.x) return a.x < b.x;
	if(a.tp != 0 && b.tp == 0) return true;   //修改排在询问前面,这里通过判断tp是否为0来区分修改和询问
	if(a.tp == 0 && b.tp != 0) return false;
	return a.tp <b.tp; 
}
inline bool cmp2(const line &a,const line &b)
{
	if(a.x != b.x) return a.x < b.x;
	if(a.tp != 0 && b.tp == 0) return false;  //到了第二部分,tp的赋值规则有所改变,cmp要跟着改变
	if(a.tp == 0 && b.tp != 0) return true;
	return a.tp <b.tp;  //你这里写true 或false 是不行的,因为sort 的 CMP 函数必须满足严格偏序关系,即具有非自反,反对称,传递性的关系,否则就会出现奇怪的 RE 和 TLE 等问题
}
line a[N*3];
inline void cdq(int l,int r)
{
	if(l == r) return;
	int mid = l + r >> 1;
	cdq(l,mid);cdq(mid+1,r);
	//左半边矩形对右半边点的贡献
	
	int tot = 0;
	for(int i=l;i<=mid;i++)
		if(Q[i].tp == 2) 
		a[++tot] = line(Q[i].a1,Q[i].b1,Q[i].b2,1,0),
		a[++tot] = line(Q[i].a2+1,Q[i].b1,Q[i].b2,-1,0);
	for(int i=mid+1;i<=r;i++)
		if(Q[i].tp == 1)
			a[++tot] = line(Q[i].x,Q[i].y,Q[i].y,0,i);
	sort(a+1,a+tot+1,cmp1);
	for(int i=1;i<=tot;i++)
	{
		if(a[i].tp != 0)
		inc(a[i].l,a[i].r,a[i].tp);
		else ans[a[i].id] += Sum(a[i].l);
	}
	for(int i=1;i<=tot;i++) if(a[i].tp != 0) inc(a[i].l,a[i].r,-a[i].tp);
	tot = 0;
	//左半边点对右半边矩形的贡献
	for(int i=l;i<=mid;i++)
		if(Q[i].tp == 1)
			a[++tot] = line(Q[i].x,Q[i].y,Q[i].y,0,0);
	for(int i=mid+1;i<=r;i++)
		if(Q[i].tp == 2)
			a[++tot] = line(Q[i].a1-1,Q[i].b1,Q[i].b2,-1,i),
			a[++tot] = line(Q[i].a2,Q[i].b1,Q[i].b2,1,i);
	sort(a+1,a+tot+1,cmp2);
	for(int i=1;i<=tot;i++)
	{
		if(a[i].tp == 0) upd(a[i].l,1);
		else
			ans[a[i].id] += a[i].tp * Qry(a[i].l,a[i].r);
	}
	for(int i=1;i<=tot;i++) if(a[i].tp == 0) upd(a[i].l,-1);  //清空,不要Memset,cdq(l,r) 的算贡献的复杂度必须控制在 r-l 量级,才能保证总复杂度正确
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		int tp;
		scanf("%d",&tp);
		if(tp == 1)
		{
			int x,y;
			scanf("%d%d",&x,&y);
			Q[i] = event(x,y);
			valy[++leny] = y;
		}
		else
		{
			int a1,b1,a2,b2;
			scanf("%d%d%d%d",&a1,&b1,&a2,&b2);
			Q[i] = event(a1,b1,a2,b2);
			valy[++leny] = b1;valy[++leny] = b2;
		}
	}
	sort(valy+1,valy+leny+1);
	leny = unique(valy+1,valy+leny+1) - valy - 1;
	for(int i=1;i<=n;i++)
		if(Q[i].tp == 1) Q[i].y = idx(Q[i].y);
		else Q[i].b1 = idx(Q[i].b1),Q[i].b2 = idx(Q[i].b2);
	cdq(1,n);
	for(int i=1;i<=n;i++) ans[i] += ans[i-1];
	for(int i=1;i<=n;i++) printf("%lld\n",ans[i]);
	return 0;
}

回复

10 条回复,欢迎继续交流。

正在加载回复...