矩形周长

#include <bits/stdc++.h>
using namespace std;
#define maxn 100100
int c[maxn],n,m,ans,d[maxn],minn[maxn*5],sum[maxn*5],lazy[maxn*5];
struct re
{
    int a,b;
}tmp[maxn],a[maxn],b[maxn];
struct ree
{
    int h,t,x;
}p[maxn*5];
void updata(int x)
{
    minn[x]=min(minn[x*2],minn[x*2+1]);
    if (minn[x*2]==minn[x*2+1]) sum[x]=(sum[x*2]+sum[x*2+1]);
    else if (minn[x*2]<minn[x*2+1]) sum[x]=sum[x*2];
    else      sum[x]=sum[x*2+1];
}
#define mid (h+t)/2
void build(int x,int h,int t)
{
    p[x].h=h; p[x].t=t; minn[x]=0;
    if (h==t)
    {
      p[x].x=d[h]; sum[x]=p[x].x;
      return;
    }
    build(x*2,h,mid); build(x*2+1,mid+1,t);
    p[x].x=p[x*2].x+p[x*2+1].x;
    updata(x);
}
bool cmp(re x,re y)
{
    if (x.a<y.a||(x.a==y.a&&x.b%2>y.b%2))
      return(true); else return(false);
}
void down(int x)
{
    if (lazy[x])
    {
        minn[x]+=lazy[x];
        if (p[x].h!=p[x].t)
        {
          lazy[x*2]+=lazy[x];
          lazy[x*2+1]+=lazy[x];
        }
        lazy[x]=0;
    }
}
void insert(int x,int h,int t,int sum) 
{
  down(x);
  if (p[x].h>t||p[x].t<h) return;
  if (h<=p[x].h&&p[x].t<=t)
  {
      if (sum==1) lazy[x]++; else lazy[x]--;
      down(x);
      return;
  }    
  insert(x*2,h,t,sum); insert(x*2+1,h,t,sum);
  updata(x);
}
int query(int x,int h,int t)
{
  down(x);
  if (p[x].h>t||p[x].t<h) return(0);
  if (h<=p[x].h&&p[x].t<=t)
  {
      if (minn[x]!=0)return(0);else return(sum[x]);
  }
  return(query(x*2,h,t)+query(x*2+1,h,t));
}
int main()
{
    freopen("noip.in","r",stdin);
    freopen("noip.out","w",stdout);
    cin>>n;
    for (int i=1;i<=n;i++)
    {
      cin>>a[i*2-1].a>>b[i*2-1].a>>a[i*2].a>>b[i*2].a;
      a[i*2-1].b=i*2-1; b[i*2-1].b=i*2-1;
      a[i*2].b=i*2;  b[i*2].b=i*2;
    }
    sort(a+1,a+1+2*n,cmp); 
    sort(b+1,b+1+2*n,cmp);
    int ll=0;b[0].a=99999999;
    for (int i=1;i<=2*n;i++)
    {
        if (b[i].a!=b[i-1].a)
        { 
          d[ll]=b[i].a-b[i-1].a;
          ll++;
        }
        c[b[i].b]=ll;
    }
    ll--; build(1,1,ll);
    for (int i=1;i<=2*n;i++)
    {
      int x=(a[i].b-1)/2+1;
      if (a[i].b%2==0) insert(1,c[x*2-1],c[x*2]-1,-1);
      ans+=query(1,c[x*2-1],c[x*2]-1);
      if (a[i].b%2==1) insert(1,c[x*2-1],c[x*2]-1,1); 
    }
    memcpy(tmp,a,sizeof(tmp));
    memcpy(a,b,sizeof(b));
    memcpy(b,tmp,sizeof(tmp)); 
    ll=0;b[0].a=99999999; memset(lazy,0,sizeof(lazy));
    for (int i=1;i<=2*n;i++)
    {
        if (b[i].a!=b[i-1].a)
        { 
          d[ll]=b[i].a-b[i-1].a;
          ll++;
        }
        c[b[i].b]=ll;
    }
    ll--; build(1,1,ll);
    for (int i=1;i<=2*n;i++)
    {
      int x=(a[i].b-1)/2+1;
      if (a[i].b%2==0) insert(1,c[x*2-1],c[x*2]-1,-1);
      ans+=query(1,c[x*2-1],c[x*2]-1);
      if (a[i].b%2==1) insert(1,c[x*2-1],c[x*2]-1,1); 
    }
    cout<<ans;
}
View Code

链接:https://www.luogu.org/problemnew/show/P1856

题解:

和维护面积基本一致,将行列分开处理,线段树维护最小值和最小值的个数就可以了

另外注意先加边后删边(避免重复计算)

原文地址:https://www.cnblogs.com/yinwuxiao/p/8394961.html