1818: [Cqoi2010]内部白点

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 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

Sample Output

5

数据范围
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 }
View Code

相关文章:

  • 2021-05-23
  • 2021-09-16
  • 2021-04-28
  • 2022-12-23
  • 2021-07-17
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
猜你喜欢
  • 2021-06-05
  • 2022-02-19
  • 2021-12-27
  • 2021-09-19
  • 2021-08-13
  • 2022-02-11
  • 2021-12-26
相关资源
相似解决方案