过程用DFS实现。
具体看代码。
最坏复杂度O(n^2),但是常数小,配合2个剪枝,在OJ跑8ms,和扫描线时间差不多,省去了建树的空间。
最坏深度是N,一般的数据不会爆栈,但是如果数据估计卡,每次DFS到最深的话,时间就和n^2差不多了。
两个剪枝是很容易想到的。
#include<cstring> #include<cstdio> struct node{ int x1,y1,x2,y2,col; }p[1005]; int max(int &a,int &b){return a>b?a:b;} int min(int &a,int &b){return a>b?b:a;} int n; int ans[2505]; bool vis[2505]; void pf(int x1,int y1,int x2,int y2,int col,int c) //x1y1为左下的坐标 x2y2为右上的坐标 { if(x1>=x2||y1>=y2) return; //剪枝1 现在的范围已经不存在了 while(c<=n&&((x2<=p[c].x1)||(y2<=p[c].y1)||(x1>=p[c].x2)||(y1>=p[c].y2))) c+=1; //剪枝2 如果现在的范围和当前判断的矩形不相交就直接判下一个 不加这个犀利的剪枝大概400ms if(c>n) { ans[col]+=(x2-x1)*(y2-y1); return; } if(y1<p[c].y1) pf(max(p[c].x1,x1),y1,max(p[c].x1,x2),min(p[c].y1,y2),col,c+1); if(y2>p[c].y2) pf(min(x1,p[c].x2),max(y1,p[c].y2),min(p[c].x2,x2),y2,col,c+1); if(x1<p[c].x1) pf(x1,min(p[c].y2,y1),min(p[c].x1,x2),min(p[c].y2,y2),col,c+1); if(x2>p[c].x2) pf(max(p[c].x2,x1),max(p[c].y1,y1),x2,max(p[c].y1,y2),col,c+1); } int main(){ int T; scanf("%d",&T); p[0].x1=p[0].y1=0,p[0].col=1; while(T--){ scanf("%d%d%d",&p[0].x2,&p[0].y2,&n); //把整个范围看成一个矩形 memset(vis,0,sizeof(vis)); memset(ans,0,sizeof(ans)); for(int i=1;i<=n;++i) { scanf("%d%d%d%d%d",&p[i].x1,&p[i].y1,&p[i].x2,&p[i].y2,&p[i].col); vis[p[i].col]=1; } vis[1]=1; for(int i=0;i<=n;++i) pf(p[i].x1,p[i].y1,p[i].x2,p[i].y2,p[i].col,i+1); for(int i=1;i<=2505;++i) { if(vis[i]&&ans[i]) printf("%d %d\n",i,ans[i]); } } }