扫描线 & 矩形面积并

code on 26.7.16

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define lson (rt<<1)
#define rson (rt<<1|1)
using namespace std;
constexpr int maxn=2e6+10,p=1e9+7;
int read()
{
    int x=0,f=1;
    char ch=getchar();
    while (ch<'0' || ch>'9')
    {
        if (ch == '-') f=-1;
        ch=getchar();
    }
    while (ch>='0' && ch<='9')
    {
        x=(x<<1)+(x<<3)+ch-'0';
        ch=getchar();
    }
    return x*f;
}
struct _
{
    int xa,xb,y,b;
    bool operator < (_ a) const {return y<a.y;}
}lin[maxn];
struct __ {int l,r,sum,cnt;}tr[maxn];
int lc,cnt,n,ans,a[maxn],xa,xb,ya,yb;
void Pushup(int rt)
{
    if (tr[rt].cnt) tr[rt].sum=a[tr[rt].r+1]-a[tr[rt].l];
    else tr[rt].sum=tr[lson].sum+tr[rson].sum;
}
void Build(int rt,int l,int r)
{
    tr[rt].l=l,tr[rt].r=r;
    if (l == r) return;
    int mid=(l+r) >> 1;
    Build(lson,l,mid),Build(rson,mid+1,r);
}
void Upd(int rt,int l,int r,int val)
{
    if (l<=tr[rt].l && tr[rt].r<=r)
    {
        tr[rt].cnt+=val;
        Pushup(rt);
        return;
    }
    int mid=(tr[rt].l+tr[rt].r) >> 1;
    if (l<=mid) Upd(lson,l,r,val);
    if (r>mid) Upd(rson,l,r,val);
    Pushup(rt);
}
signed main()
{
    n=read();
    for (int i=1;i<=n;i++)
    {
        xa=read(),ya=read(),xb=read(),yb=read();
        lc++;lin[lc]={xa,xb,ya,0};
        lc++;lin[lc]={xa,xb,yb,1};
        a[i]=xa,a[i+n]=xb;
    }
    sort(a+1,a+1+n*2);
    cnt=unique(a+1,a+1+n*2)-a-1;
    sort(lin+1,lin+1+n*2);
    Build(1,1,cnt-1);
    for (int i=1;i<=n*2;i++)
    {
        _ l=lin[i];
        if (i>1) ans+=tr[1].sum*(lin[i].y-lin[i-1].y);
        if (l.b)
        {
            int u,v;
            u=lower_bound(a+1,a+1+cnt,l.xa)-a;
            v=lower_bound(a+1,a+1+cnt,l.xb)-a-1;
            Upd(1,u,v,-1);
        }
        else
        {
            int u,v;
            u=lower_bound(a+1,a+1+cnt,l.xa)-a;
            v=lower_bound(a+1,a+1+cnt,l.xb)-a-1;
            Upd(1,u,v,1);
        }
    }
    printf("%lld\n",ans);
    return 0;
}

code(展示从上往下扫,从左往右扫同理)

#include<bits/stdc++.h>
using namespace std;
#define lson (rt << 1)
#define rson (rt << 1 | 1)
struct lline
{
	long long xa,xb,y;
	bool b;
	bool operator<(lline a)const
	{
		return y<a.y;
	}
}line[2000010];
struct node
{
	long long l,r,sum,cnt;
	//这个cnt其实只是管区间是否完全覆盖的 方便对于整段线段的修改 
}tree[2000010];
int lc,cnt;
int n;
long long ans;
long long a[2000010];
long long xa,xb,ya,yb;
void pushup(int rt)
{
	if (tree[rt].cnt) tree[rt].sum=a[tree[rt].r+1]-a[tree[rt].l];//完全覆盖(+1注意)
	else tree[rt].sum=tree[lson].sum+tree[rson].sum;//不一定完全覆盖 
}
void build(int rt,int l,int r)
{
	tree[rt].l=l;
	tree[rt].r=r;
	if (l == r)return;
	int mid = (l+r) >> 1;
	build(lson,l,mid);
	build(rson,mid+1,r);
}
void update(int rt,int l,int r,int val)
{
	if (l<=tree[rt].l && tree[rt].r<=r)
	{
		tree[rt].cnt += val;//这个是更新被覆盖的次数的
		pushup(rt);//这个是更新被覆盖的次数的
		return;
	}
	int mid = (tree[rt].l+tree[rt].r) >> 1;
	if (l<=mid) update(lson,l,r,val);
	if (r>mid) update(rson,l,r,val);
	pushup(rt);
}
int main()
{
	cin >> n;
	for (int i=1;i<=n;i++)
	{
		cin >> xa >> ya >> xb >> yb;
		//先插入一条线段 
		line[++lc].xa=xa;
		line[lc].xb=xb;
		line[lc].y = ya;
		line[lc].b=false;
		//再撤销一条线段 
		line[++lc].xa=xa;
		line[lc].xb=xb;
		line[lc].y = yb;
		line[lc].b=true;
		//离散化 
		a[i]=xa;
		a[i+n]=xb;
	}
	sort(a+1,a+1+n*2);//由于n是正方体数,所以要*2
	cnt = unique(a+1,a+1+n*2)-a-1;
	//离散化
	sort(line+1,line+1+n*2);
	//扫描线一定是一个有序的处理过程,在某个点把与该点有关的全部改好 
    //所以记得先排个序 
	build(1,1,cnt-1);//由于在pushup中+1了,所以这里也要-1
	for (int i=1;i<=n*2;i++)
	{
		lline l = line[i];
		if (i>1) ans += tree[1].sum*(line[i].y-line[i-1].y);
		if (l.b)
		{
			int u,v;
			u = lower_bound(a+1,a+1+cnt,l.xa)-a;
			v = lower_bound(a+1,a+1+cnt,l.xb)-a-1;//由于会出现扫到点的情况(如[3,3]),-1就能避免
			update(1,u,v,-1);//-1即为撤销 
		}
		else
		{
			int u,v;
			u = lower_bound(a+1,a+1+cnt,l.xa)-a;
			v = lower_bound(a+1,a+1+cnt,l.xb)-a-1;//-1同上
			update(1,u,v,1);//1即为增加 
		}
	}
	cout << ans <<endl;
	return 0;
}

code2 动态开点、从左往右扫 from wang79

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+10;
#define lson v[rt].ls
#define rson v[rt].rs
ll n,root,tot,y[maxn],val[maxn],sum,ans;
struct mcx
{
	ll x=0,y1=0,y2=0;
	bool in=0;
}v1[maxn];
bool cmp(mcx x,mcx y)
{
	return x.x<y.x;
}
struct nd
{
	ll ls=0,rs=0,cnt=0,len=0;
}v[19*maxn];
ll query(ll x)
{
	ll h=1,t=sum,ans=0;
	while(h<=t)
	{
		ll mid=(h+t)>>1;
		if(x<=val[mid])
		{
			ans=mid;
			t=mid-1;
		}
		else h=mid+1;
	}
	return ans;
}
void pushup(ll rt,ll l,ll r)
{
	if(v[rt].cnt) v[rt].len=val[r+1]-val[l];
	else v[rt].len=v[lson].len+v[rson].len;
}
void update(ll &rt,ll l,ll r,ll L,ll R,ll k)
{
	if(!rt) rt=++tot;
	if(l>=L&&r<=R)
	{
		v[rt].cnt+=k;
		pushup(rt,l,r);
		return;
	}
	ll mid=(l+r)>>1;
	if(L<=mid) update(lson,l,mid,L,R,k);
	if(R>mid) update(rson,mid+1,r,L,R,k);
	pushup(rt,l,r);
}
int main () 
{
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		int x1,y1,x2,y2;
		cin>>x1>>y1>>x2>>y2;
		v1[i].x=x1;v1[i].y1=y1;v1[i].y2=y2;v1[i].in=true;
		v1[i+n].x=x2;v1[i+n].y1=y1;v1[i+n].y2=y2;v1[i+n].in=false;
		y[i]=y1;
		y[i+n]=y2;
	}
	stable_sort(y+1,y+1+2*n);
	stable_sort(v1+1,v1+1+2*n,cmp);
	for(int i=1;i<=2*n;i++) if(y[i]!=y[i-1]) val[++sum]=y[i];
	for(int i=1;i<=2*n;i++)
	{
//		cout<<i<<" "<<v[1].len<<"\n";
		ans+=v[1].len*(v1[i].x-v1[i-1].x);
//		cout<<i<<" "<<query(v1[i].y1)<<" "<<query(v1[i].y2)<<" "<<endl;
		if(v1[i].in) update(root,1,sum,query(v1[i].y1),query(v1[i].y2)-1,1);
		else update(root,1,sum,query(v1[i].y1),query(v1[i].y2)-1,-1);
	}
	cout<<ans;
    return 0;
}

code3(验证cnt不用-1(???))from zhangji

#include<bits/stdc++.h> 
using namespace std;

#define lson (rt<<1)
#define rson (rt<<1|1)
#define int long long

const int N = 2e6+10;
typedef long long ll;

inline void read(int &x)//加速输入 
{
	char ch=getchar();int f=1;x=0;
	while(!isdigit(ch) && ch^'-') ch=getchar();
	if(ch=='-') f=-1,ch=getchar();
	while(isdigit(ch)) x=x*10+ch-'0',ch=getchar();
	x*=f;
}

struct smx{
	int y1,y2,x,cnt;
	bool aaa;
}line[N];

bool cmp(smx a,smx b){
	return a.x < b.x;
}
int a[N];
struct node{
	int l,r,len,cnt;
}tr[N];

void build(int rt,int l,int r){
	tr[rt].l=l,tr[rt].r=r;
	if(l==r) return;
	int mid=(l+r)>>1;
	build(lson,l,mid);
	build(rson,mid+1,r);
}

void pushup(int rt){
	if(tr[rt].cnt) tr[rt].len=a[tr[rt].r+1]-a[tr[rt].l];
	else tr[rt].len = tr[lson].len + tr[rson].len;
}

void update(int rt,int l,int r,int k){
	if(l<=tr[rt].l && r>=tr[rt].r) {
		tr[rt].cnt+=k;
		pushup(rt);
		return;
	}
	
	int mid=(tr[rt].l+tr[rt].r)>>1;
	if(mid>=l) update(lson,l,r,k);
	if(r>mid) update(rson,l,r,k);
	pushup(rt);
}

int n,ans;

signed main(){
	
	//输入 
	cin >> n;
	int x1,y1,x2,y2,op=0;
	for(int i=1;i<=n;i++){
		cin >> x1 >> y1 >> x2 >> y2;
		line[++op].x = x1;
		line[op].y1 = y1;
		line[op].y2 = y2;
		line[op].aaa = 0;
		line[++op].x = x2;
		line[op].y1 = y1;
		line[op].y2 = y2;
		line[op].aaa = 1;
		a[i]=y1;
		a[i+n]=y2;
	}
	
	//离散化
	sort(a+1,a+1+n*2);
	int cnt = unique(a+1,a+1+2*n)-a-1;
	sort(line+1,line+1+2*n,cmp);
	build(1,1,cnt); 
	
	//开始骚妙
	for(int i=1;i<=n<<1;i++) {
		if(i>1) ans+=tr[1].len*(line[i].x-line[i-1].x);
		
		if(line[i].aaa) update(1,lower_bound(a+1,a+1+cnt,line[i].y1)-a,lower_bound(a+1,a+1+cnt,line[i].y2)-a-1,-1);
		else update(1,lower_bound(a+1,a+1+cnt,line[i].y1)-a,lower_bound(a+1,a+1+cnt,line[i].y2)-a-1,1);	
	}
	cout << ans;
	return 0;
}

注

  • 注释来源于老学长_2K22_
posted @ 2026-03-24 11:42  msjing  阅读(13)  评论(0)    收藏  举报