首先你要知道这样一个物理学结论:【水能流过的地方,光也能经过】
于是乎只要左右连通就可以了。
对偶一下,就是只要上下界不要连通就可以了。
于是建图最小割,把每个点拆点,i->i+n,1
如果与上界有交就连边S->i,inf
如果与下界有交就连边i+n->T,inf
如果i,j相交了就互相连边。
然后此题毒瘤的地方就在于各种判交…
你需要耐心…
数据比较友好,没有出了矩形ABCD的器件。
#include <bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define ll long long
#define N 610
inline char gc(){
static char buf[1<<16],*S,*T;
if(T==S){T=(S=buf)+fread(buf,1,1<<16,stdin);if(T==S) return EOF;}
return *S++;
}
inline int read(){
int x=0,f=1;char ch=gc();
while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=gc();}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc();
return x*f;
}
int n,H,h[N],num=1,T=605,lev[N],ans=0,cur[N];
struct Icefox{
int op,x1,y1,x2,y2;
}a[310];
struct edge{
int to,next,val;
}data[200000];
inline void add(int x,int y,int val){
data[++num].to=y;data[num].next=h[x];h[x]=num;data[num].val=val;
data[++num].to=x;data[num].next=h[y];h[y]=num;data[num].val=0;
}
inline ll sqr(ll x){return x*x;}
inline ll dis(int x1,int y1,int x2,int y2){return sqr(x1-x2)+sqr(y1-y2);}
inline bool jud(int x,int y){
if(a[x].op==1&&a[y].op==1) return dis(a[x].x1,a[x].y1,a[y].x1,a[y].y1)<=sqr(a[x].x2+a[y].x2);
if(a[x].op==2&&a[y].op==2){
if(a[y].x1<=a[x].x1&&a[y].x2>=a[x].x1&&a[x].y1<=a[y].y1&&a[x].y2>=a[y].y1) return 1;
if(a[y].x1<=a[x].x1&&a[y].x2>=a[x].x1&&a[x].y1<=a[y].y2&&a[x].y2>=a[y].y2) return 1;
if(a[y].x1<=a[x].x2&&a[y].x2>=a[x].x2&&a[x].y1<=a[y].y1&&a[x].y2>=a[y].y1) return 1;
if(a[y].x1<=a[x].x2&&a[y].x2>=a[x].x2&&a[x].y1<=a[y].y2&&a[x].y2>=a[y].y2) return 1;
if(a[y].y1<=a[x].y1&&a[y].y2>=a[x].y1&&a[x].x1<=a[y].x1&&a[x].x2>=a[y].x1) return 1;
if(a[y].y1<=a[x].y1&&a[y].y2>=a[x].y1&&a[x].x1<=a[y].x2&&a[x].x2>=a[y].x2) return 1;
if(a[y].y1<=a[x].y2&&a[y].y2>=a[x].y2&&a[x].x1<=a[y].x1&&a[x].x2>=a[y].x1) return 1;
if(a[y].y1<=a[x].y2&&a[y].y2>=a[x].y2&&a[x].x1<=a[y].x2&&a[x].x2>=a[y].x2) return 1;
return 0;
}if(a[x].op==2) swap(x,y);
if(dis(a[x].x1,a[x].y1,a[y].x1,a[y].y1)<=sqr(a[x].x2)) return 1;
if(dis(a[x].x1,a[x].y1,a[y].x1,a[y].y2)<=sqr(a[x].x2)) return 1;
if(dis(a[x].x1,a[x].y1,a[y].x2,a[y].y1)<=sqr(a[x].x2)) return 1;
if(dis(a[x].x1,a[x].y1,a[y].x2,a[y].y2)<=sqr(a[x].x2)) return 1;
if(abs(a[x].x1-a[y].x1)<=a[x].x2&&a[x].y1>=a[y].y1&&a[x].y1<=a[y].y2) return 1;
if(abs(a[x].x1-a[y].x2)<=a[x].x2&&a[x].y1>=a[y].y1&&a[x].y1<=a[y].y2) return 1;
if(abs(a[x].y1-a[y].y1)<=a[x].x2&&a[x].x1>=a[y].x1&&a[x].x1<=a[y].x2) return 1;
if(abs(a[x].y1-a[y].y2)<=a[x].x2&&a[x].x1>=a[y].x1&&a[x].x1<=a[y].x2) return 1;
return 0;
}
inline bool bfs(){
queue<int>q;memset(lev,0,sizeof(lev));
q.push(0);lev[0]=1;
while(!q.empty()){
int x=q.front();q.pop();
for(int i=h[x];i;i=data[i].next){
int y=data[i].to;if(lev[y]||!data[i].val) continue;
lev[y]=lev[x]+1;if(y==T) return 1;q.push(y);
}
}return 0;
}
inline int dinic(int x,int low){
if(x==T) return low;int tmp=low;
for(int &i=cur[x];i;i=data[i].next){
int y=data[i].to;if(lev[y]!=lev[x]+1||!data[i].val) continue;
int res=dinic(y,min(tmp,data[i].val));
if(!res) lev[y]=0;else tmp-=res,data[i].val-=res,data[i^1].val+=res;
if(!tmp) return low;
}return low-tmp;
}
int main(){
// freopen("a.in","r",stdin);
read();H=read();n=read();
for(int i=1;i<=n;++i){
a[i].op=read();a[i].x1=read();a[i].y1=read();
a[i].x2=read();if(a[i].op==2) a[i].y2=read();
add(i,n+i,1);
if(a[i].op==1){
if(a[i].y1+a[i].x2>=H) add(0,i,inf);
if(a[i].y1-a[i].x2<=0) add(n+i,T,inf);
}else{
if(a[i].y2>=H) add(0,i,inf);
if(a[i].y1<=0) add(n+i,T,inf);
}for(int j=1;j<i;++j) if(jud(i,j)) add(n+i,j,inf),add(n+j,i,inf);
}while(bfs()){memcpy(cur,h,sizeof(h));ans+=dinic(0,inf);}
printf("%d\n",ans);
return 0;
}