Bzoj1818: [Cqoi2010]内部白点 && Tyvj P2637 内部白点 扫描线,树状数组,离散化
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 }
AC程序
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define MAXN 100010 4 struct node 5 { 6 int x,y; 7 }p[MAXN]; 8 struct NODE 9 { 10 int x,y,pos; 11 }pp[MAXN]; 12 struct Au 13 { 14 int l,r,t; 15 }s[MAXN*3];//这一定要开三倍. 16 int BIT[MAXN],n,xx[MAXN]; 17 int read() 18 { 19 int s=0,fh=1;char ch=getchar(); 20 while(ch<'0'||ch>'9'){if(ch=='-')fh=-1;ch=getchar();} 21 while(ch>='0'&&ch<='9'){s=s*10+(ch-'0');ch=getchar();} 22 return s*fh; 23 } 24 bool cmp1(NODE a,NODE b) 25 { 26 if(a.y==b.y)return a.x<b.x; 27 return a.y<b.y; 28 } 29 bool cmp2(NODE a,NODE b) 30 { 31 if(a.x==b.x)return a.y<b.y; 32 return a.x<b.x; 33 } 34 bool cmp3(Au a,Au b) 35 { 36 if(p[a.l].y==p[b.l].y)return p[a.l].x<p[a.l].x; 37 return p[a.l].y<p[b.l].y; 38 } 39 int lowbit(int o){return o&(-o);} 40 void Add(int k,int add) 41 { 42 while(k<=n) 43 { 44 BIT[k]+=add; 45 k+=lowbit(k); 46 } 47 } 48 int Sum(int k) 49 { 50 int sum=0; 51 while(k>0) 52 { 53 sum+=BIT[k]; 54 k-=lowbit(k); 55 } 56 return sum; 57 } 58 int main() 59 { 60 int i,cnt,sum,cx,wx,wx1; 61 n=read(); 62 for(i=1;i<=n;i++){p[i].x=read();p[i].y=read();xx[i]=p[i].x;pp[i].x=p[i].x;pp[i].y=p[i].y;pp[i].pos=i;} 63 sort(pp+1,pp+n+1,cmp1);//按纵坐标从小到大排,纵坐标相等按横坐标从小到大排.(处理出来横线.) 64 cnt=0; 65 for(i=1;i<n;i++)//存储横线要存左右端点坐标. 66 { 67 if(pp[i].y==pp[i+1].y) 68 { 69 s[++cnt].l=pp[i].pos;s[cnt].r=pp[i+1].pos;s[cnt].t=0; 70 } 71 } 72 sort(pp+1,pp+n+1,cmp2); 73 for(i=1;i<n;i++)//存储竖线只用存上下端点. 74 { 75 if(pp[i].x==pp[i+1].x) 76 { 77 s[++cnt].l=pp[i].pos;s[cnt].r=pp[i].pos;s[cnt].t=1;//下端点. 78 s[++cnt].l=pp[i+1].pos;s[cnt].r=pp[i+1].pos;s[cnt].t=-1;//上端点. 79 } 80 } 81 sort(s+1,s+cnt+1,cmp3); 82 /*for(i=n;i>1;i--) 83 { 84 if(p[s[i].l].y==p[s[i-1].l].y) 85 }*/ 86 memset(BIT,0,sizeof(BIT));sum=n; 87 sort(xx+1,xx+n+1); 88 cx=unique(xx+1,xx+n+1)-(xx+1); 89 //sort(yy+1,yy+n+1); 90 //cy=unique(yy+1,yy+n+1)-(yy+1); 91 for(i=1;i<=cnt;i++) 92 { 93 if(s[i].t==0) 94 { 95 wx=lower_bound(xx+1,xx+cx+1,p[s[i].r].x)-(xx+1); 96 wx1=lower_bound(xx+1,xx+cx+1,p[s[i].l].x)-(xx+1); 97 sum+=(Sum(wx)-Sum(wx1+1)); 98 } 99 else 100 { 101 wx=lower_bound(xx+1,xx+cx+1,p[s[i].l].x)-(xx+1); 102 //if(wx==0&&xx[1]==p[s[i].l].x)wx=1; 103 Add(wx+1,s[i].t); 104 } 105 } 106 printf("%d",sum); 107 fclose(stdin); 108 fclose(stdout); 109 return 0; 110 }
id