扫描线 & 矩形面积并
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_
$\mathscr{msjing}$

浙公网安备 33010602011771号