[IOI1998] Pictures

用线段树维护区间最小值和最小值个数来求一段区间里0的个数,把横的和竖的边分别拿出来,排序,然后每次查一下重复部分的长度即可

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
#define MAXN 5000
#define MAXL 10000
#define mid (T[k].l+T[k].r)/2
using namespace std;
inline 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*10+ch-'0'; ch=getchar();}
    return x*f;
} 
 
int n,cnt=0,ans=0;
struct sq{
    int x1,y1,x2,y2;
}s[MAXN+5];
struct line{
    int k,l,r,x;
}l[MAXL+5];
struct TREE{
    int l,r,x,num,val;
}T[MAXL*10];
 
bool cmp(line x,line y){return x.x<y.x||(x.x==y.x&&x.k<y.k);}
 
void pushdown(int k)
{
    int ls=k<<1,rs=(k<<1)+1;
    T[ls].x+=T[k].val;T[rs].x+=T[k].val;
    T[ls].val+=T[k].val;T[rs].val+=T[k].val;
    T[k].val=0;
}
 
void combine(int k)
{
    int ls=k<<1,rs=(k<<1)+1;
    if(T[ls].x==T[rs].x) T[k].x=T[ls].x,T[k].num=T[ls].num+T[rs].num;
    else if(T[ls].x<T[rs].x) T[k].x=T[ls].x,T[k].num=T[ls].num;
    else T[k].x=T[rs].x,T[k].num=T[rs].num;
}
 
void renew(int k,int l,int r,int ad)
{
    if(T[k].l==l&&T[k].r==r)
    {T[k].x+=ad;T[k].val+=ad;return;}
    if(T[k].val) pushdown(k);
    if(r<=mid) renew(k<<1,l,r,ad);
    else if(l>mid) renew((k<<1)+1,l,r,ad);
    else {renew(k<<1,l,mid,ad);renew((k<<1)+1,mid+1,r,ad);}
    combine(k);
}
 
int query(int k,int l,int r)
{
//  cout<<"q"<<k<<" "<<l<<" "<<r<<endl;
    if(T[k].l==l&&T[k].r==r)
    {
        if(T[k].x>0) return T[k].r-T[k].l+1;
        else return T[k].r-T[k].l+1-T[k].num;   
    }
    if(T[k].val) pushdown(k);
    if(r<=mid) return query(k<<1,l,r);
    else if(l>mid) return query((k<<1)+1,l,r);
    else return query((k<<1)+1,mid+1,r)+query(k<<1,l,mid);
}
 
void init(int k,int l,int r)
{
    //cout<<"init"<<k<<" "<<r<<endl;
    T[k].l=l;T[k].r=r;T[k].val=0;
    if(l==r){T[k].x=0;T[k].num=1;return;}
    init(k<<1,l,mid);init((k<<1)+1,mid+1,r);
    combine(k);
}
 
int main()
{
    n=read();
    for(int i=1;i<=n;++i)
    {
        s[i].x1=read()+10001;s[i].y1=read()+10001;
        s[i].x2=read()+10001;s[i].y2=read()+10001;
        ans+=(s[i].x2+s[i].y2-s[i].y1-s[i].x1)*2;
        l[++cnt].k=0;l[cnt].x=s[i].x1;l[cnt].l=s[i].y1+1;l[cnt].r=s[i].y2;
        l[++cnt].k=1;l[cnt].x=s[i].x2;l[cnt].l=s[i].y1+1;l[cnt].r=s[i].y2;
    }
    sort(l+1,l+cnt+1,cmp);init(1,1,20005);
//  for(int i=1;i<=cnt;i++)
//  {
//      cout<<l[i].k<<" "<<l[i].x<<" "<<l[i].l<<" "<<l[i].r<<endl;
//  }
    for(register int i=1;i<=cnt;i++)
    {
        if(!l[i].k){ans-=query(1,l[i].l,l[i].r);renew(1,l[i].l,l[i].r,1);}
        else       {renew(1,l[i].l,l[i].r,-1);ans-=query(1,l[i].l,l[i].r);}
         
    }
    cnt=0;
    for(register int i=1;i<=n;++i)
    {
        l[++cnt].k=0;l[cnt].x=s[i].y1;l[cnt].l=s[i].x1+1;l[cnt].r=s[i].x2;
        l[++cnt].k=1;l[cnt].x=s[i].y2;l[cnt].l=s[i].x1+1;l[cnt].r=s[i].x2;
    }
    sort(l+1,l+cnt+1,cmp);init(1,1,20005);
//  for(int i=1;i<=cnt;i++)
//  {
//      cout<<l[i].k<<" "<<l[i].x<<" "<<l[i].l<<" "<<l[i].r<<endl;
//  }
    for(register int i=1;i<=cnt;i++)
    {
        if(!l[i].k){ans-=query(1,l[i].l,l[i].r);renew(1,l[i].l,l[i].r,1);}
        else       {renew(1,l[i].l,l[i].r,-1);ans-=query(1,l[i].l,l[i].r);}
    }
    printf("%d",ans);
    return 0;
}
FallDream代表秋之国向您问好! 欢迎您来我的博客www.cnblogs.com/FallDream
原文地址:https://www.cnblogs.com/FallDream/p/ioi1998.html