1818: [Cqoi2010]内部白点
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 704 Solved: 344
[Submit][Status][Discuss]
Description
无限大正方形网格里有n个黑色的顶点,所有其他顶点都是白色的(网格的顶点即坐标为整数的点,又称整点)。每秒钟,所有内部白点同时变黑,直到不存在内部白点为止。你的任务是统计最后网格中的黑点个数。 内部白点的定义:一个白色的整点P(x,y)是内部白点当且仅当P在水平线的左边和右边各至少有一个黑点(即存在x1 < x < x2使得(x1,y)和(x2,y)都是黑点),且在竖直线的上边和下边各至少有一个黑点(即存在y1 < y < y2使得(x,y1)和(x,y2)都是黑点)。
Input
输入第一行包含一个整数n,即初始黑点个数。以下n行每行包含两个整数(x,y),即一个黑点的坐标。没有两个黑点的坐标相同,坐标的绝对值均不超过109。
Output
输出仅一行,包含黑点的最终数目。如果变色过程永不终止,输出-1。
Sample Input
4
0 2
2 0
-2 0
0 -2
0 2
2 0
-2 0
0 -2
Sample Output
5
数据范围
36%的数据满足:n < = 500
64%的数据满足:n < = 30000
100%的数据满足:n < = 100000
数据范围
36%的数据满足:n < = 500
64%的数据满足:n < = 30000
100%的数据满足:n < = 100000
HINT
-1的情况很好搞,在纸上画画就看出来了。(黄学长博客中有证明:http://hzwer.com/1836.html )
之后我们发现,其实只用找有多少个白点上下左右都为黑点。
然后我们就想到了可以用扫描线。。。
把每个竖线和横线找到。
从下往上扫描,
遇到竖线的下端点就 让坐标+1。
遇到横线就去统计 在 l~r 中的和。
遇到竖线的上端点就 让坐标 -1。
这个用树状数组维护一下即可。
代码和对拍:
丑陋的对拍:
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define INF 1e9 4 int a[2000][2000],X[10010],Y[10010]; 5 int main() 6 { 7 int sum,i,j,x,y,xx,yy,xx1,yy1,dx,dy,n,pd; 8 scanf("%d",&n); 9 xx=-INF;yy=-INF;xx1=INF;yy1=INF; 10 for(i=1;i<=n;i++){scanf("%d %d",&X[i],&Y[i]);xx=max(xx,X[i]);yy=max(yy,Y[i]);xx1=min(xx1,X[i]);yy1=min(yy1,Y[i]);} 11 dx=(int)fabs(xx1);dy=(int)fabs(yy1); 12 for(i=1;i<=n;i++) 13 { 14 X[i]+=dx;Y[i]+=dy; 15 a[X[i]][Y[i]]=1; 16 } 17 sum=n; 18 for(i=xx1+dx;i<=xx+dx;i++) 19 { 20 for(j=yy1+dy;j<=yy+dy;j++) 21 { 22 if(a[i][j]==0) 23 { 24 pd=0; 25 x=i;y=j; 26 while(x<=xx+dx){if(a[x][y]==1){pd++;break;}x++;} 27 x=i;y=j; 28 while(y<=yy+dy){if(a[x][y]==1){pd++;break;}y++;} 29 x=i;y=j; 30 while(x>=xx1+dx){if(a[x][y]==1){pd++;break;}x--;} 31 x=i;y=j; 32 while(y>=yy1+dy){if(a[x][y]==1){pd++;break;}y--;} 33 if(pd==4)sum++; 34 } 35 } 36 } 37 printf("%d",sum); 38 return 0; 39 } 40 41 42 43 44 45 46 #include<bits/stdc++.h> 47 using namespace std; 48 bool vis[2010][2010]; 49 int add=1000; 50 int main() 51 { 52 srand(time(0)); 53 int n,i,x,y; 54 n=rand()%1000+1; 55 printf("%d\n",n); 56 for(i=1;i<=n;i++) 57 { 58 while(1) 59 { 60 x=rand()%1000-500;y=rand()%1000-500; 61 if(vis[x+add][y+add]==false) 62 { 63 vis[x+add][y+add]=true; 64 break; 65 } 66 } 67 printf("%d %d\n",x,y); 68 } 69 return 0; 70 }