bzoj1905: Soldier 士兵控制的棋盤

傳送門
首先我們大力轉換座標系。
然後我們做一遍掃描線求出矩形面積的交。
然後我們減去在外面的部分,可以發現一定是等腰三角形
在搞一個面積並就可以了
時間複雜度O(NlogN)

#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 300030
#define ll long long 
using namespace std;
ll max(ll x,int y){
    return x>y?x:y;
}
struct Squ{ll x,y,r;}s[N];
struct L{
    ll x,y1,y2,k;
    friend bool operator <(L a,L b){
        return a.x<b.x;
    }
};
struct Tri{
    ll st,ed;
    ll sqr(){
        if ((ed-st+1)&1) return (ed-st+2)*((ed-st+1)/2+1)/2;
        return (ed-st+3)*((ed-st-1)/2+1)/2;
    }
    friend bool operator <(Tri a,Tri b){
        return a.st<b.st;
    }
};
int n,m,k;
struct segment{
    int tag[N*4],ans[N*4],p[N];
    void clear(){
        memset(tag,0,sizeof(tag));
        memset(ans,0,sizeof(ans));
    }
    void update(int k,ll l,ll r){
        if (tag[k]>0) ans[k]=r-l;
        else ans[k]=ans[k*2]+ans[k*2+1];
    }
    void add(int k,int l,int r,int x,int y,int v){
        int mid=(l+r)/2;
        if (x<=p[l]&&p[r]<=y) tag[k]+=v;
        else{
            if (x<p[mid]) add(k*2,l,mid,x,y,v);
            if (p[mid]<y) add(k*2+1,mid,r,x,y,v);
        }
        update(k,p[l],p[r]);
    }
    ll ask(){
        return ans[1];
    }
}T;
struct calSqu{
    L l[N];
    int tot,n;
    ll x1[N],x2[N],y1[N],y2[N];
    ll calc(){
        T.clear();
        for (int i=1;i<=n;i++)
            T.p[i*2-1]=y1[i],T.p[i*2]=y2[i];
        sort(T.p+1,T.p+2*n+1);
        tot=1;
        for (int i=2;i<=2*n;i++)
            if (T.p[i]!=T.p[i-1])
                T.p[++tot]=T.p[i];
        for (int i=1;i<=n;i++){
            l[i*2-1]=(L){x1[i],y1[i],y2[i],1};
            l[i*2]=(L){x2[i],y1[i],y2[i],-1}; 
        }
        sort(l+1,l+2*n+1);
        ll ans=0,la=0;
        for (int i=1;i<=2*n;i++){
            if (i!=1) ans+=la*(ll)(l[i].x-l[i-1].x);
            if (l[i].y1!=l[i].y2) T.add(1,1,tot,l[i].y1,l[i].y2,l[i].k);
            la=T.ask();
        }
        return ans;
    }
}Cal;
struct calTri{
    int n;
    Tri t[N],tmp;
    ll calc(){
        if (!n) return 0ll;
        sort(t+1,t+n+1);
        ll ans=t[1].sqr(); int x=1;
        for (int i=2;i<=n;i++){
            if (t[i].st>=t[x].st&&t[i].ed<=t[x].ed) continue;
            if (t[i].st>t[x].ed){
                ans+=t[i].sqr(); x=i; continue;
            }
            ans+=t[i].sqr();
            tmp=(Tri){t[i].st,t[x].ed};
            ans-=tmp.sqr();
            x=i;
        }
        return ans;
    }
}Tr;
int main(){
    scanf("%d%d%d",&n,&m,&k);
    for (int i=1;i<=k;i++)
        scanf("%lld%lld%lld",&s[i].x,&s[i].y,&s[i].r);
    Cal.n=k;
    for (int i=1;i<=k;i++){
        int tmp=s[i].r-((s[i].x+s[i].y+s[i].r)&1);
        Cal.x1[i]=(s[i].y+s[i].x-tmp)/2;
        Cal.y1[i]=(s[i].y-s[i].x-tmp)/2;
        Cal.x2[i]=(s[i].y+s[i].x+tmp)/2+1;
        Cal.y2[i]=(s[i].y-s[i].x+tmp)/2+1;
    }
    ll ans=Cal.calc();
    for (int i=1;i<=k;i++){
        int tmp=s[i].r-(!((s[i].x+s[i].y+s[i].r)&1));
        Cal.x1[i]=(s[i].y+s[i].x-tmp-1)/2;
        Cal.y1[i]=(s[i].y-s[i].x-tmp-1)/2;
        Cal.x2[i]=(s[i].y+s[i].x+tmp-1)/2+1;
        Cal.y2[i]=(s[i].y-s[i].x+tmp-1)/2+1;
    }
    ans+=Cal.calc();
    Tr.n=0;
    for (int i=1;i<=k;i++)
        if (s[i].r>=s[i].x){
            ++Tr.n;
            Tr.t[Tr.n].st=s[i].y-(s[i].r-s[i].x);
            Tr.t[Tr.n].ed=s[i].y+(s[i].r-s[i].x);
        }
    ans-=Tr.calc();
    Tr.n=0;
    for (int i=1;i<=k;i++)
        if (s[i].r>=s[i].y){
            ++Tr.n;
            Tr.t[Tr.n].st=s[i].x-(s[i].r-s[i].y);
            Tr.t[Tr.n].ed=s[i].x+(s[i].r-s[i].y);
        }
    ans-=Tr.calc();
    Tr.n=0;
    for (int i=1;i<=k;i++)
        if (s[i].r>=n+1-s[i].x){
            ++Tr.n;
            Tr.t[Tr.n].st=s[i].y-(s[i].r-(n+1-s[i].x));
            Tr.t[Tr.n].ed=s[i].y+(s[i].r-(n+1-s[i].x));
        }
    ans-=Tr.calc();
    Tr.n=0;
    for (int i=1;i<=k;i++)
        if (s[i].r>=m+1-s[i].y){
            ++Tr.n;
            Tr.t[Tr.n].st=s[i].x-(s[i].r-(m+1-s[i].y));
            Tr.t[Tr.n].ed=s[i].x+(s[i].r-(m+1-s[i].y));
        }
    ans-=Tr.calc();
    ll m1=0,m2=0,m3=0,m4=0;
    for (int i=1;i<=k;i++){
        if (s[i].r>=s[i].x+s[i].y) m1=max(m1,1+s[i].r-s[i].x-s[i].y);
        if (s[i].r>=s[i].x+(m+1-s[i].y)) m2=max(m2,1+s[i].r-s[i].x-(m+1-s[i].y));
        if (s[i].r>=(n+1-s[i].x)+s[i].y) m3=max(m3,1+s[i].r-(n+1-s[i].x)-s[i].y);
        if (s[i].r>=(n+1-s[i].x)+(m+1-s[i].y)) m4=max(m4,1+s[i].r-(n+1-s[i].x)-(m+1-s[i].y));
    }
    ans+=(m1*m1+m2*m2+m3*m3+m4*m4+m1+m2+m3+m4)/2;
    printf("%lld",ans);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章