1. 程式人生 > 實用技巧 >#掃描線,線段樹#洛谷 3875 [TJOI2010]被汙染的河流

#掃描線,線段樹#洛谷 3875 [TJOI2010]被汙染的河流

題目


分析

矩陣面積並不是掃描線模板題嗎
然後連題目都沒仔細看就交了
發現它是一個線段向外擴充套件一個格子qwq


程式碼

#include <cstdio>
#include <cctype>
#include <algorithm>
#define rr register
using namespace std;
const int N=200011; long long ans;
struct rec{int x,l,r,w;}b[N];
int n,k,w[N<<2],lazy[N<<2],a[N];
inline signed iut(){
	rr int ans=0; rr char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
	return ans; 
}
inline void update(int k,int l,int r,int x,int y,int end){
	if (l==x&&r==y){
		lazy[k]+=end;
		if (lazy[k]) w[k]=a[r+1]-a[l];
            else if (l==r) w[k]=0;
                else w[k]=w[k<<1]+w[k<<1|1];
		return;
	}
	rr int mid=(l+r)>>1;
	if (y<=mid) update(k<<1,l,mid,x,y,end);
	else if (x>mid) update(k<<1|1,mid+1,r,x,y,end);
	else update(k<<1,l,mid,x,mid,end),update(k<<1|1,mid+1,r,mid+1,y,end);
	if (lazy[k]) w[k]=a[r+1]-a[l];
        else w[k]=w[k<<1]+w[k<<1|1];
}
bool cmp(rec a,rec b){return a.x<b.x||(a.x==b.x&&a.w>b.w);}
signed main(){
	for (rr int m=iut();m;--m){
		rr int xa=iut(),ya=iut(),xb=iut(),yb=iut();
		if (xa>xb) xa^=xb,xb^=xa,xa^=xb;
		if (ya>yb) ya^=yb,yb^=ya,ya^=yb;
		if (xa==xb){
			b[++k]=(rec){xa-1,ya,yb,1},
			b[++k]=(rec){xa+1,ya,yb,-1},
			a[++n]=ya,a[++n]=yb;
		}else{
			b[++k]=(rec){xa,ya-1,yb+1,1},
			b[++k]=(rec){xb,ya-1,yb+1,-1},
			a[++n]=ya-1,a[++n]=yb+1;
		}
	}
	sort(a+1,a+1+n),sort(b+1,b+1+k,cmp),n=unique(a+1,a+1+n)-a-1;
	for (rr int i=1;i<k;++i){
		rr int l=lower_bound(a+1,a+1+n,b[i].l)-a,
		       r=lower_bound(a+1,a+1+n,b[i].r)-a-1;
		update(1,1,n,l,r,b[i].w),ans+=1ll*(b[i+1].x-b[i].x)*w[1];
	}
	return !printf("%lld",ans);
}