bzoj3228 [ SDOI2008 ] -- 扫描线 + 线段树

来源:互联网 发布:吴江法院拍卖公告淘宝 编辑:程序博客网 时间:2024/06/05 08:01

首先曼哈顿距离有如下性质:

|x1x2|+|y1y2|=max(|x1y1(x2y2)|,|x1+y1(x2+y2)|)

于是将点 (x,y) 的坐标转化为 (xy,x+y),点控制的范围就变成了一个正方形,扫描线+线段树即可。
注意转化后的坐标系中 x+y 为奇数的点是不存在的,所以线段树还要维护奇数的个数。

代码

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;inline char nc(){    static char buf[100000],*p1=buf,*p2=buf;    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;}inline void Read(int& x){    char c=nc();    for(;c<'0'||c>'9';c=nc());    for(x=0;c>='0'&&c<='9';x=(x<<3)+(x<<1)+c-48,c=nc());}#define N 100010#define M 5000000#define INF 200000000#define ll long longstruct Line{    int w,f;    bool d;}b[N<<1];struct Node{    int x,y,w;}a[N];long long Ans;int i,j,k,n,m,t,num,T,cnt,c[M],C[M],cl[M],cr[M],p[M],L[N],R[N],Rt,m1,m2,M1,M2;int d[N];inline bool Cmp(Line a,Line b){    return a.w<b.w;}inline void Update(int& x,int l,int r,int L,int R,int y){    if(l>R||r<L)return;    if(!x)x=++cnt;    if(l>=L&&r<=R){        p[x]+=y;        c[x]=(p[x]>0?r-l+1:c[cl[x]]+c[cr[x]]);        C[x]=(p[x]>0?(r-l+1>>1)+((l%2&&r%2)?1:0):C[cl[x]]+C[cr[x]]);        return;    }    int Mid=l+r>>1;    Update(cl[x],l,Mid,L,R,y);Update(cr[x],Mid+1,r,L,R,y);    c[x]=(p[x]>0?r-l+1:c[cl[x]]+c[cr[x]]);    C[x]=(p[x]>0?(r-l+1>>1)+((l%2&&r%2)?1:0):C[cl[x]]+C[cr[x]]);}inline bool Cmp1(Node a,Node b){    return a.y<b.y;}inline ll Get(int a,int b,int c,int d){    if(a>=b)return 0;    c=max(c,0);d=max(d,0);    if(a==b-1)return max(c,d-1);    if(!c&&!d)return 0;    if(!c)return d<b-a?1ll*d*(d-1)/2:1ll*(2*d-b+a-1)*(b-a)/2;    if(!d)return c<b-a?1ll*c*(c+1)/2:1ll*(2*c-b+a+1)*(b-a)/2;    if(c+d<=b-a+1)return 1ll*c*(c+1)/2+1ll*d*(d-1)/2;    int x=c-d+b-a>>1;    if(x<0)return 1ll*(2*d-b+a-1)*(b-a)/2;    if(x>=b-a-1)return 1ll*(2*c-b+a+1)*(b-a)/2;    if(x*2==c-d+b-a)return 1ll*(c*2-x+1)*x/2+1ll*(d*2-b+a+x-1)*(b-a-x)/2;    return 1ll*(c*2-x+1)*x/2+1ll*(d*2-b+a+x-1)*(b-a-x)/2+1;}inline void Solve1(){    sort(a+1,a+k+1,Cmp1);    d[k]=a[k].w-n+a[k].x-a[k].y;    for(i=k-1;i;i--)d[i]=max(d[i+1],a[i].w-n+a[i].x-a[i].y);    t=-INF;d[k+1]=-INF;a[0].y=M1;a[k+1].y=M2;    for(i=0;i<=k;i++){        if(i)t=max(t,a[i].w-n+a[i].x+a[i].y);        Ans-=Get(i?a[i].y:M1,i<k?a[i+1].y:M2,t-a[i].y,d[i+1]+a[i+1].y);    }    if(t-M2>0)Ans-=t-M2;    d[k]=a[k].w+1-a[k].x-a[k].y;    for(i=k-1;i;i--)d[i]=max(d[i+1],a[i].w+1-a[i].x-a[i].y);    t=-INF;    for(i=0;i<=k;i++){        if(i)t=max(t,a[i].w+1-a[i].x+a[i].y);        Ans-=Get(i?a[i].y:M1,i<k?a[i+1].y:M2,t-a[i].y,d[i+1]+a[i+1].y);    }    if(t-M2>0)Ans-=t-M2;}inline void Solve2(){    sort(a+1,a+k+1,Cmp1);    d[k]=a[k].w-n+a[k].x-a[k].y;    for(i=k-1;i;i--)d[i]=max(d[i+1],a[i].w-n+a[i].x-a[i].y);    t=-INF;d[k+1]=-INF;a[0].y=1;a[k+1].y=m;    for(i=0;i<=k;i++){        if(i)t=max(t,a[i].w-n+a[i].x+a[i].y);        Ans-=Get(i?a[i].y:1,i<k?a[i+1].y:m,t-a[i].y,d[i+1]+a[i+1].y);    }    if(t-m>0)Ans-=t-m;    d[k]=a[k].w+1-a[k].x-a[k].y;    for(i=k-1;i;i--)d[i]=max(d[i+1],a[i].w+1-a[i].x-a[i].y);    t=-INF;    for(i=0;i<=k;i++){        if(i)t=max(t,a[i].w+1-a[i].x+a[i].y);        Ans-=Get(i?a[i].y:1,i<k?a[i+1].y:m,t-a[i].y,d[i+1]+a[i+1].y);    }    if(t-m>0)Ans-=t-m;}int main(){    Read(n);Read(m);Read(k);    m1=M1=INF;m2=M2=-INF;    for(i=1;i<=k;i++){        Read(a[i].x);Read(a[i].y);Read(a[i].w);        a[i].w=min(a[i].w,INF);        M1=min(M1,a[i].y-a[i].w);M2=max(M2,a[i].y+a[i].w);        t=a[i].x,a[i].x-=a[i].y,a[i].y+=t;        L[i]=a[i].y-a[i].w;R[i]=a[i].y+a[i].w;        b[++num].f=i;b[num].w=a[i].x-a[i].w;        b[++num].f=i;b[num].w=a[i].x+a[i].w+1;b[num].d=1;        m1=min(m1,L[i]);m2=max(m2,R[i]);    }    sort(b+1,b+num+1,Cmp);    for(i=1;i<=num;i=j+1){        for(j=i;j<=num&&b[j+1].w==b[j].w;){            Update(Rt,m1,m2,L[b[j].f],R[b[j].f],b[j].d?-1:1);            j++;        }        if(j<=num)Update(Rt,m1,m2,L[b[j].f],R[b[j].f],b[j].d?-1:1);        if(j<num){            Ans+=1ll*(b[j+1].w-b[i].w)/2*c[Rt];            if(!(b[i].w%2)&&b[j+1].w%2)Ans+=c[Rt]-C[Rt];            if((b[i].w%2)&&!(b[j+1].w%2))Ans+=C[Rt];        }    }    for(i=1;i<=k;i++)t=a[i].x,a[i].x=a[i].x+a[i].y>>1,a[i].y=a[i].y-t>>1;    Solve1();    for(i=1;i<=k;i++)swap(a[i].x,a[i].y);    swap(n,m);    Solve2();    cout<<Ans<<endl;    return 0;}
原创粉丝点击