Bzoj1818: [Cqoi2010]内部白点 && Tyvj P2637 内部白点 扫描线,树状数组,离散化
2016-03-11 15:01
417 查看
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
40 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。
这个用树状数组维护一下即可。
代码和对拍:
丑陋的对拍:
#include<bits/stdc++.h> using namespace std; #define MAXN 100010 struct node { int x,y; }p[MAXN]; struct NODE { int x,y,pos; }pp[MAXN]; struct Au { int l,r,t; }s[MAXN*3];//这一定要开三倍. int BIT[MAXN],n,xx[MAXN]; int read() { int s=0,fh=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')fh=-1;ch=getchar();} while(ch>='0'&&ch<='9'){s=s*10+(ch-'0');ch=getchar();} return s*fh; } bool cmp1(NODE a,NODE b) { if(a.y==b.y)return a.x<b.x; return a.y<b.y; } bool cmp2(NODE a,NODE b) { if(a.x==b.x)return a.y<b.y; return a.x<b.x; } bool cmp3(Au a,Au b) { if(p[a.l].y==p[b.l].y)return p[a.l].x<p[a.l].x; return p[a.l].y<p[b.l].y; } int lowbit(int o){return o&(-o);} void Add(int k,int add) { while(k<=n) { BIT[k]+=add; k+=lowbit(k); } } int Sum(int k) { int sum=0; while(k>0) { sum+=BIT[k]; k-=lowbit(k); } return sum; } int main() { int i,cnt,sum,cx,wx,wx1; n=read(); 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;} sort(pp+1,pp+n+1,cmp1);//按纵坐标从小到大排,纵坐标相等按横坐标从小到大排.(处理出来横线.) cnt=0; for(i=1;i<n;i++)//存储横线要存左右端点坐标. { if(pp[i].y==pp[i+1].y) { s[++cnt].l=pp[i].pos;s[cnt].r=pp[i+1].pos;s[cnt].t=0; } } sort(pp+1,pp+n+1,cmp2); for(i=1;i<n;i++)//存储竖线只用存上下端点. { if(pp[i].x==pp[i+1].x) { s[++cnt].l=pp[i].pos;s[cnt].r=pp[i].pos;s[cnt].t=1;//下端点. s[++cnt].l=pp[i+1].pos;s[cnt].r=pp[i+1].pos;s[cnt].t=-1;//上端点. } } sort(s+1,s+cnt+1,cmp3); /*for(i=n;i>1;i--) { if(p[s[i].l].y==p[s[i-1].l].y) }*/ memset(BIT,0,sizeof(BIT));sum=n; sort(xx+1,xx+n+1); cx=unique(xx+1,xx+n+1)-(xx+1); //sort(yy+1,yy+n+1); //cy=unique(yy+1,yy+n+1)-(yy+1); for(i=1;i<=cnt;i++) { if(s[i].t==0) { wx=lower_bound(xx+1,xx+cx+1,p[s[i].r].x)-(xx+1); wx1=lower_bound(xx+1,xx+cx+1,p[s[i].l].x)-(xx+1); sum+=(Sum(wx)-Sum(wx1+1)); } else { wx=lower_bound(xx+1,xx+cx+1,p[s[i].l].x)-(xx+1); //if(wx==0&&xx[1]==p[s[i].l].x)wx=1; Add(wx+1,s[i].t); } } printf("%d",sum); fclose(stdin); fclose(stdout); return 0; }
View Code
id
相关文章推荐
- Android EditText的设置
- 如何让光标处于EditText的末尾
- PostgreSQL学习记录-- 2016-03-11
- SQL server2012怎么备份数据库(设置自动备份)
- tomcat servlet 线程
- jquery.cookie中的操作
- C#:String.Format数字格式化输出 {0:N2} {0:D2} {0:C2}...
- 如何查看hadoop是32位还是64位
- JDBC实例 Statement,PreparedStatement,CallableStatement三个方法的实例
- C++ RTTI 机制
- linux(centos6.5)安装开发环境jdk,tomcat.idea,git,maven,postgresql,rabbitmq
- Linux基础命令总结
- 个人介绍——海边的成长
- 实验0:了解和熟悉操作系统
- 实验0:了解和熟悉操作系统
- javascript基础笔记
- YUV420P像素数据编码为JPEG图片
- [国嵌攻略][132][串口驱动实现]
- Injection Attacks-XML注入
- /etc/resolv.conf中内容被清空的解决办法