这种题目太恶心
把坐标轴转一下 就是裸的扫描线
但是是网格 很恶心
我用线段树算出无边界的情况 分奇数列和偶数列算两次
然后四个边界算一下去掉
四个角重复减的算一下 加回去
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#define cl(x) memset(x,0,sizeof(x))
using namespace std;
typedef long long ll;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
return *p1++;
}
inline void read(int &x){
char c=nc(),b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}
const int N=400005;
int sx[N],icnt;
int sum[N];
inline int Bin(int x){
return lower_bound(sx+1,sx+icnt+1,x)-sx;
}
int T[N<<2],F[N<<2];
inline void Pushup(int x,int l,int r){
if (F[x]) T[x]=sum[r+1]-sum[l];
else T[x]=T[x<<1]+T[x<<1|1];
}
inline void Add(int x,int l,int r,int ql,int qr,int qt){
if (ql<=l && r<=qr){
F[x]+=qt;
Pushup(x,l,r);
return;
}
int mid=(l+r)>>1;
if (qr<=mid)
Add(x<<1,l,mid,ql,qr,qt);
else if (ql>mid)
Add(x<<1|1,mid+1,r,ql,qr,qt);
else
Add(x<<1,l,mid,ql,mid,qt),Add(x<<1|1,mid+1,r,mid+1,qr,qt);
Pushup(x,l,r);
}
int n,m,K;
struct sold{
int x,y,r;
void read(){
::read(x); ::read(y); ::read(r);
}
}S[N];
struct event{
int x,y1,y2,f;
event() { }
event(int x,int y1,int y2,int f):x(x),y1(y1),y2(y2),f(f) { }
bool operator < (const event &B) const{
return x<B.x;
}
}eve[N];
int tot;
ll Ans;
inline void Solve(int d){
int l,r,y1,y2;
tot=0; icnt=0; cl(sx); cl(sum);
for (int i=1;i<=K;i++){
l=S[i].x-S[i].y-S[i].r; r=S[i].x-S[i].y+S[i].r;
y1=S[i].x-S[i].r+S[i].y; y2=S[i].x+S[i].r+S[i].y;
if ((l&1)==d)
l++,r--,y1++,y2--;
if (l>r) continue;
y1>>=1; y2>>=1;
sx[++icnt]=y1; sx[++icnt]=y2+1;
eve[++tot]=event(l,y1,y2,1);
eve[++tot]=event(r+2,y1,y2,-1);
}
sort(sx+1,sx+icnt+1);
icnt=unique(sx+1,sx+icnt+1)-sx-1;
for (int i=1;i<=icnt;i++) sum[i]+=sum[i-1]+sx[i]-sx[i-1];
sort(eve+1,eve+tot+1);
int last=-1<<30,p=1,cur;
while (p<=tot){
cur=eve[p].x;
Ans+=(ll)(cur-last)/2*T[1];
while (p<=tot && eve[p].x==cur){
Add(1,1,icnt,Bin(eve[p].y1),Bin(eve[p].y2+1)-1,eve[p].f);
p++;
}
last=cur;
}
}
struct abcd{
int l,r;
abcd(int l=0,int r=0):l(l),r(r) { }
bool operator < (const abcd &B) const{
return l==B.l?r<B.r:l<B.l;
}
}seg[N];
int scnt;
inline ll calc(int l,int r){
if (l>r) return 0;
if ((r-l)&1){
int t=(r-l)/2;
return (ll)t*(t+1)+2*(t+1);
}else{
int t=(r-l)/2;
return (ll)t*(t+1)+t+1;
}
}
inline void Calc(){
if (!scnt) return;
sort(seg+1,seg+scnt+1);
int p=1,pnt=0,now,maximum=-1<<30; ll ret=0;
while (p<=scnt){
now=seg[p].l;
while (p+1<=scnt && seg[p+1].l==now)
p++;
if (seg[p].r>maximum){
maximum=seg[p].r;
seg[++pnt]=seg[p];
}
p++;
}
scnt=pnt;
ret=calc(seg[1].l,seg[1].r);
for (int i=2;i<=scnt;i++){
ret-=calc(seg[i].l,seg[i-1].r);
ret+=calc(seg[i].l,seg[i].r);
}
Ans-=ret;
}
int main(){
int lu=1<<30,ld=1<<30,ru=1<<30,rd=1<<30;
int tem,t1,t2;
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
read(n); read(m); read(K);
for (int i=1;i<=K;i++)
S[i].read();
Solve(0);
Solve(1);
scnt=0;
t1=0; t2=0;
for (int i=1;i<=K;i++){
if (S[i].y-S[i].r>0) continue;
tem=1-(S[i].y-S[i].r);
seg[++scnt]=abcd(S[i].x-tem+1,S[i].x+tem-1);
t1=max(t1,1-(S[i].x-tem+1));
t2=max(t2,(S[i].x+tem-1)-n);
}
ld=min(lu,t1); rd=min(rd,t2);
Calc();
scnt=0;
t1=0; t2=0;
for (int i=1;i<=K;i++){
if (S[i].y+S[i].r<=m) continue;
tem=S[i].y+S[i].r-m;
seg[++scnt]=abcd(S[i].x-tem+1,S[i].x+tem-1);
t1=max(t1,1-(S[i].x-tem+1));
t2=max(t2,(S[i].x+tem-1)-n);
}
lu=min(lu,t1); ru=min(ru,t2);
Calc();
scnt=0;
t1=0; t2=0;
for (int i=1;i<=K;i++){
if (S[i].x-S[i].r>0) continue;
tem=1-(S[i].x-S[i].r);
seg[++scnt]=abcd(S[i].y-tem+1,S[i].y+tem-1);
t1=max(t1,1-(S[i].y-tem+1));
t2=max(t2,(S[i].y+tem-1)-m);
}
ld=min(ld,t1); lu=min(lu,t2);
Calc();
scnt=0;
t1=0; t2=0;
for (int i=1;i<=K;i++){
if (S[i].x+S[i].r<=n) continue;
tem=S[i].x+S[i].r-n;
seg[++scnt]=abcd(S[i].y-tem+1,S[i].y+tem-1);
t1=max(t1,1-(S[i].y-tem+1));
t2=max(t2,(S[i].y+tem-1)-m);
}
rd=min(rd,t1); ru=min(ru,t2);
Calc();
Ans+=(ll)(lu+1)*lu/2+(ll)(ld+1)*ld/2+(ll)(ru+1)*ru/2+(ll)(rd+1)*rd/2;
printf("%lld\n",Ans);
return 0;
}