模板扫描线求查错
查看原帖
模板扫描线求查错
122784
_Blue_楼主2021/9/6 22:47

加了些注释

  • 2 WA 8 TLE
  • 不很清楚自己的做法是否正确
Code
#include <bits/stdc++.h>
using namespace std;
int n;
int num;
int tmp_[400005];
struct node{
	int l,r,len,ti;
	//ti表示被完整覆盖的次数 
	//len表示被截取的长度 
}t[800005];
struct line_{
	int dy,x1,x2;
	bool v;
}a[200005];
int cnt;
int f[400005];
inline int ls(int p){return p<<1;}
inline int rs(int p){return p<<1|1;}
void built(int p,int l,int r){
	//对于一个点的情况没必要记录 
	if(l==r) return;
	t[p].l=l,t[p].r=r;
	//l+1==r,说明但前是叶子结点,记录最小线段的状态 
	if(l+1==r) return;
	int mid=(r-l>>1)+l;
	//原区间[l,r]拆分为[l,mid][mid,r] 
	built(ls(p),l,mid);
	built(rs(p),mid,r);
}
bool cmp(line_ x,line_ y){
	if(x.dy==y.dy) return x.v>y.v;
	return x.dy<y.dy;
}
int last;
int ans;
int tag[800005];
inline void f_(int p,int k){
	tag[p]+=k;
	t[p].ti+=k;
	t[p].len=f[t[p].r]-f[t[p].l];
}
inline void push_down(int p){
	f_(ls(p),tag[p]);
	f_(rs(p),tag[p]);
	tag[p]=0;
}
inline void push_up(int p){
	int l=ls(p),r=rs(p);
	t[p].ti=min(t[l].ti,t[r].ti);
	//两个叶子结点被完整覆盖的次数的最小值是父亲节点被覆盖的次数 
	t[p].len=t[l].len+t[r].len;//长度为两个相加 
}
inline void add(int p,int rl,int rr,int k){
	//没有交集,退出 
	if(rr<=f[t[p].l]||rl>=f[t[p].r]) return;
	if(t[p].l+1==t[p].r){//查询到了叶子结点 
		if(k==1){
			t[p].ti++;//ti表示被完整覆盖的次数 
			//len表示长度 
			if(t[p].ti) t[p].len=f[t[p].r]-f[t[p].l];
		} 
		else{
			t[p].ti--;
			if(!t[p].ti) t[p].len=0;
		}
		return;
	}
	if(tag[p]) push_down(p);
	add(ls(p),rl,rr,k);
	add(rs(p),rl,rr,k);
	push_up(p);
}
int main(){
	//从下往上扫 
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		int tx1,ty1,tx2,ty2;
		scanf("%d%d%d%d",&tx1,&ty1,&tx2,&ty2);
		a[++cnt]=(line_){ty1,tx1,tx2,1};
		a[++cnt]=(line_){ty2,tx1,tx2,0};
		//存储所有的横坐标 
		tmp_[++num]=tx1;
		tmp_[++num]=tx2;
	}
	cnt=0;
	//对横坐标离散化 
	sort(tmp_+1,tmp_+num+1);
	for(int i=1;i<=num;i++){
		if(f[cnt]!=tmp_[i])
			f[++cnt]=tmp_[i];
		//f[l]对应的是这个点的横坐标 
	}
	//建树 
	built(1,1,cnt);
	sort(a+1,a+2*n+1,cmp);
	last=a[1].dy;
	for(int i=1;i<=2*n;i++){
		//每当出现了横边,说明截取的线段长度发生了改变
		//这时要计算之前的面积,以及修改线段的状态 
		if(a[i].v){//新加入了线段 
			ans+=(a[i].dy-last)*t[1].len;
			last=a[i].dy;
			add(1,a[i].x1,a[i].x2,1);
		}
		else{//矩形的上边
			ans+=(a[i].dy-last)*t[1].len;
			last=a[i].dy;
			add(1,a[i].x1,a[i].x2,-1);
		}
	}
	printf("%d\n",ans);
} 
2021/9/6 22:47
加载中...