bzoj3228 [ SDOI2008 ] -- 扫描线 + 线段树
2017-09-24 19:34
267 查看
首先曼哈顿距离有如下性质:
|x1−x2|+|y1−y2|=max(|x1−y1−(x2−y2)|,|x1+y1−(x2+y2)|)
于是将点 (x,y) 的坐标转化为 (x−y,x+y),点控制的范围就变成了一个正方形,扫描线+线段树即可。
注意转化后的坐标系中 x+y 为奇数的点是不存在的,所以线段树还要维护奇数的个数。
|x1−x2|+|y1−y2|=max(|x1−y1−(x2−y2)|,|x1+y1−(x2+y2)|)
于是将点 (x,y) 的坐标转化为 (x−y,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 long struct Line{ int w,f; bool d; }b[N<<1]; struct Node{ int x,y,w; }a ; long long Ans; int i,j,k,n,m,t,num,T,cnt,c[M],C[M],cl[M],cr[M],p[M],L ,R ,Rt,m1,m2,M1,M2; int d ; 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; }
相关文章推荐
- [线段树 扫描线 鬼畜] BZOJ 3228 [Sdoi2008]棋盘控制 && BZOJ 1905 Soldier 士兵控制的棋盘
- bzoj 3226: [Sdoi2008]校门外的区间(线段树)
- 【BZOJ】【P3226】【Sdoi2008】【校门外的区间】【题解】【线段树】
- [线段树 标记] BZOJ 3226 [Sdoi2008]校门外的区间
- BZOJ 题目 3226: [Sdoi2008]校门外的区间(线段树区间交并差异或)
- [BZOJ]3226: [Sdoi2008]校门外的区间 线段树
- bzoj3226: [Sdoi2008]校门外的区间 线段树
- bzoj 3226 [Sdoi2008]校门外的区间(线段树)
- [BZOJ3226][SDOI2008]校门外的区间(线段树)
- [bzoj3226][Sdoi2008]校门外的区间——线段树
- BZOJ_P2049&Codevs_P1839 [SDOI2008]Cave 洞穴勘测(LCT)
- [BZOJ1012]JSOI2008 最大数|线段树|平衡树
- 【bzoj 2190】[SDOI2008]仪仗队 欧拉函数
- [BZOJ4698][Sdoi2008]Sandy的卡片(后缀数组+st表||后缀自动机)
- BZOJ2049: [Sdoi2008]Cave 洞穴勘测(洛谷P2147)
- bzoj 4515 [Sdoi2016]游戏 线段树维护凸包
- bzoj 1818: [Cqoi2010]内部白点 (扫描线+线段树)
- bzoj 2190 [SDOI2008]仪仗队
- [BZOJ2049] [SDOI2008] 洞穴勘测
- [bzoj 3231--SDOI2008]递归数列