2021.11.23 扫描线

http://acm.hdu.edu.cn/showproblem.php?pid=1542

扫描线求面积

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;

const int N=210;
int n,lazy[N<<5];
double X[N],tot[N<<5];
struct node{
	double l,r,h;
	int flag;
	bool operator <(const node &b)const{
		return h<b.h;
	}
}a[N];

inline void update(int x,int l,int r){
	if(lazy[x])tot[x]=X[r+1]-X[l];
	else if(l==r)tot[x]=0.0;
	else tot[x]=tot[x<<1]+tot[x<<1|1];
}
inline void add(int x,int l,int r,int L,int R,int k){
	if(l>=L&&r<=R)return (void)(lazy[x]+=k,update(x,l,r));
	int mid=(l+r)>>1;
	if(L<=mid)add(x<<1,l,mid,L,R,k);
	if(R>mid)add(x<<1|1,mid+1,r,L,R,k);
	update(x,l,r);
}

int main(){
	int js=0;
	while(~scanf("%d",&n)&&n){
		++js;
		printf("Test case #%d\n",js);
		memset(&a,0,sizeof(a));
		for(int i=1;i<=n;i++){
			double x,y,u,v;
			cin>>x>>y>>u>>v;
			a[i].l=a[i+n].l=x;a[i].r=a[i+n].r=u;
			a[i].h=y;a[i+n].h=v;
			a[i].flag=1;a[i+n].flag=-1;
			X[i]=x;X[i+n]=u;
		}
		sort(a+1,a+n*2+1);
		sort(X+1,X+n*2+1);
		double ans=0.0;
		int len=unique(X+1,X+n*2+1)-X-1;
		for(int i=1;i<=n*2;i++){
            //每个线段树的节点表示i到i+1这个底边区间
			int L=lower_bound(X+1,X+len+1,a[i].l)-X;
			int R=lower_bound(X+1,X+len+1,a[i].r)-X-1;
			add(1,1,len-1,L,R,a[i].flag);
			ans+=tot[1]*(a[i+1].h-a[i].h);
		}
		printf("Total explored area: %.2lf\n\n",ans);
	}
	return 0;
}

https://www.luogu.com.cn/problem/P1856

扫描线求周长

每次加入底边的长度等于这次的总底边长减去上次总底边长的绝对值;每次加入高的总长度等于总段数$\times\(2\)\times$高。

https://www.luogu.com.cn/blog/wucstdio/solution-p1856

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;

const int N=1e4+10;
int n,X[N];
struct node{
	int l,r,h,flag;
	bool operator <(const node &b)const{
		return h==b.h?flag>b.flag:h<b.h;
	}
}a[N];
struct tree{
	int l,r,tot,num,lazy;
	int flagl,flagr;
}t[N<<5];

inline void update(int x){
	if(t[x].lazy){
		t[x].tot=X[t[x].r+1]-X[t[x].l];
		t[x].num=t[x].flagl=t[x].flagr=1;
	}else if(t[x].l==t[x].r){
		t[x].tot=0;
		t[x].num=t[x].flagl=t[x].flagr=0;
	}else{
		t[x].tot=t[x<<1].tot+t[x<<1|1].tot;
		t[x].num=t[x<<1].num+t[x<<1|1].num;
		if(t[x<<1].flagr==1&&t[x<<1|1].flagl==1)--t[x].num;
		t[x].flagl=t[x<<1].flagl;t[x].flagr=t[x<<1|1].flagr;
	}
}
inline void add(int x,int l,int r,int L,int R,int k){
	if(l>=L&&r<=R)return (void)(t[x].lazy+=k,update(x));
	int mid=(l+r)>>1;
	if(L<=mid)add(x<<1,l,mid,L,R,k);
	if(R>mid)add(x<<1|1,mid+1,r,L,R,k);
	update(x);
}
inline void build(int x,int l,int r){
	t[x].l=l;t[x].r=r;t[x].num=t[x].tot=t[x].lazy=t[x].flagl=t[x].flagr=0;
	if(l==r)return ;
	int mid=(l+r)>>1;
	build(x<<1,l,mid);
	build(x<<1|1,mid+1,r);
	update(x);
}

int main(){
	ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	cin>>n;
	for(int i=1;i<=n;i++){
		int u,v,x,y;
		cin>>x>>y>>u>>v;
		a[i].l=a[i+n].l=x;a[i].r=a[i+n].r=u;
		a[i].h=y;a[i+n].h=v;
		a[i].flag=1;a[i+n].flag=-1;
		X[i]=x;X[i+n]=u;
	}
	sort(a+1,a+n*2+1);
	sort(X+1,X+n*2+1);
	//for(int i=1;i<=n*2;i++)cout<<X[i]<<" ";cout<<endl;//
	//for(int i=1;i<=n*2;i++)cout<<a[i].l<<" "<<a[i].r<<" "<<a[i].h<<" "<<a[i].flag<<endl;//
	int len=unique(X+1,X+n*2+1)-X-1;
	build(1,1,len-1);
	//cout<<"    Case 1"<<endl;//
	int ans=0,lasti=0;
	for(int i=1;i<=n*2;i++){
		int L=lower_bound(X+1,X+len+1,a[i].l)-X;
		int R=lower_bound(X+1,X+len+1,a[i].r)-X-1;
		//cout<<i<<" "<<a[i].l<<" "<<a[i].r<<" "<<L<<" "<<R<<endl;//
		add(1,1,len-1,L,R,a[i].flag);
		while(a[i].h==a[i+1].h&&a[i].flag==a[i+1].flag){
			++i;
			L=lower_bound(X+1,X+len+1,a[i].l)-X;
			R=lower_bound(X+1,X+len+1,a[i].r)-X-1;
			//cout<<i<<" "<<a[i].l<<" "<<a[i].r<<" "<<L<<" "<<R<<endl;//
			add(1,1,len-1,L,R,a[i].flag);
		}
		//cout<<"    Case 2"<<endl;//
		ans+=abs(t[1].tot-lasti);lasti=t[1].tot;
		ans+=t[1].num*2*(a[i+1].h-a[i].h);
		//cout<<"OK "<<i<<endl;// 
	}
	cout<<ans;
	return 0;
}

矩形中的点的最大权值之和转化为点所在的矩形上的最大的矩形的权值之和

https://www.luogu.com.cn/problem/P1502

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;

#define int long long
const int N=2e4+10;
int ti,n,W,H,X[N],ans;
struct node{
	int l,r,h,flag;
	bool operator <(const node &b)const{
		return h==b.h?flag>b.flag:h<b.h;
	}
}a[N];
struct tree{
	int l,r,maxn,lazy;
}t[N<<5];

inline void pushdown(int x){
	if(t[x].lazy==0)return ;
	t[x<<1].lazy+=t[x].lazy;t[x<<1|1].lazy+=t[x].lazy;
	t[x<<1].maxn+=t[x].lazy;t[x<<1|1].maxn+=t[x].lazy;
	t[x].lazy=0;
}
inline void update(int x){
	t[x].maxn=max(t[x<<1].maxn,t[x<<1|1].maxn);
}
inline void build(int x,int l,int r){
	t[x].l=l;t[x].r=r;t[x].maxn=t[x].lazy=0;
	if(l==r)return ;//(void)(update(x));
	int mid=(l+r)>>1;
	build(x<<1,l,mid);
	build(x<<1|1,mid+1,r);
	//update(x);
}
inline void add(int x,int l,int r,int L,int R,int k){
	if(l>=L&&r<=R)return (void)(t[x].lazy+=k,t[x].maxn+=k);
	int mid=(l+r)>>1;
	pushdown(x);
	if(L<=mid)add(x<<1,l,mid,L,R,k);
	if(R>mid)add(x<<1|1,mid+1,r,L,R,k);
	update(x);
}

signed main(){
	ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	cin>>ti;
	while(ti--){
		//memset(&a,0,sizeof(a));
		cin>>n>>W>>H;
		for(int i=1;i<=n;i++){
			int x,y,u,v,val;
			cin>>x>>y>>val;
			u=x+W-1;v=y+H-1;
			a[i].l=a[i+n].l=y;a[i].r=a[i+n].r=v;
			a[i].h=x;a[i+n].h=u;
			a[i].flag=val;a[i+n].flag=-val;
			X[i]=y;X[i+n]=v;
		}
		sort(X+1,X+n*2+1);
		int len=unique(X+1,X+n*2+1)-X-1;
		sort(a+1,a+n*2+1);
		build(1,1,len-1);
		ans=0;
		for(int i=1;i<=n*2;i++){
			int L=lower_bound(X+1,X+len+1,a[i].l)-X-1;
			int R=lower_bound(X+1,X+len+1,a[i].r)-X-1;
			//cout<<i<<" "<<a[i].l<<" "<<a[i].r<<" "<<L<<" "<<R<<endl;//
			add(1,1,len-1,L,R,a[i].flag);
			ans=max(ans,t[1].maxn);
			//cout<<t[1].maxn<<endl;//
		}
		cout<<ans<<endl;
	}
	return 0;
}
 posted on 2021-11-23 20:08  eleveni  阅读(29)  评论(0)    收藏  举报