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