
bzoj1818: [Cqoi2010]内部白点
发布日期:2021-05-06 23:47:48
浏览次数:21
分类:原创文章
本文共 3440 字,大约阅读时间需要 11 分钟。
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
我们发现,其实新变成的点是没有任何*用的
反正大概就是有很多线段,求一下交点什么的。。
这个的话扫一下,用个线段树维护一下就好了
具体看代码,不想写了
#include<cstdio>#include<algorithm>#include<iostream>#include<cstring>using namespace std;const int N=100005*2;int n;struct qq{ int x,y; int tx,ty;}s[N];int X1[N],X2[N];//表示X坐标是这时的最小和最大int Y1[N],Y2[N];//表示Y坐标是这时的最小和最大bool cmp (qq a,qq b){ return a.x<b.x;}bool cmp1 (qq a,qq b){ return a.y<b.y;}int XX,YY;void init (){ scanf("%d",&n); for (int u=1;u<=n;u++) scanf("%d%d",&s[u].x,&s[u].y);}void prepare (){ memset(X1,127,sizeof(X1));memset(X2,0,sizeof(X2)); memset(Y1,127,sizeof(Y1));memset(Y2,0,sizeof(Y2)); sort(s+1,s+1+n,cmp); s[1].tx=1; for (int u=2;u<=n;u++) { s[u].tx=s[u-1].tx; if (s[u].x!=s[u-1].x) s[u].tx++; }XX=s[n].tx; sort(s+1,s+1+n,cmp1); s[1].ty=1; for (int u=2;u<=n;u++) { s[u].ty=s[u-1].ty; if (s[u].y!=s[u-1].y) s[u].ty++; }YY=s[n].ty; for (int u=1;u<=n;u++) { X1[s[u].tx]=min(X1[s[u].tx],s[u].ty),X2[s[u].tx]=max(X2[s[u].tx],s[u].ty); Y1[s[u].ty]=min(Y1[s[u].ty],s[u].tx),Y2[s[u].ty]=max(Y2[s[u].ty],s[u].tx); }/* printf("\n"); for (int u=1;u<=n;u++) printf("%d %d\n",s[u].tx,s[u].ty); printf("\n"); for (int u=1;u<=XX;u++) printf("%d %d\n",X1[u],X2[u]); printf("\n"); for (int u=1;u<=YY;u++) printf("%d %d\n",Y1[u],Y2[u]); printf("\n");*/}struct qy{ int x,y; int z;}a[N];int cnt=0;struct qa{ int l,r; int s1,s2; int c;}tr[N*2];int num=0;bool cmp2 (qy x,qy y){ return x.x<y.x;}void bt (int l,int r){ int a=++num; tr[a].l=l;tr[a].r=r; tr[a].c=0; if (l==r) return ; int mid=(l+r)>>1; tr[a].s1=num+1;bt(l,mid); tr[a].s2=num+1;bt(mid+1,r);}void update (int now){ if (tr[now].c==0) return ; int s1=tr[now].s1,s2=tr[now].s2; tr[s1].c+=tr[now].c; tr[s2].c+=tr[now].c; tr[now].c=0;}void change (int now,int l,int r){ if (tr[now].l==l&&tr[now].r==r) {tr[now].c++;return ;} update(now); int s1=tr[now].s1,s2=tr[now].s2; int mid=(tr[now].l+tr[now].r)>>1; if (r<=mid) change(s1,l,r); else if (l>mid) change(s2,l,r); else change(s1,l,mid),change(s2,mid+1,r);}int get (int now,int x){ if (tr[now].l==tr[now].r) return tr[now].c; update(now); int s1=tr[now].s1,s2=tr[now].s2; int mid=(tr[now].l+tr[now].r)>>1; if (x<=mid) return get(s1,x); else return get(s2,x);}void solve (){ int ans=0; for (int u=1;u<=YY;u++) { a[++cnt].x=Y1[u]-1; a[cnt].y=u; a[cnt].z=-1; a[++cnt].x=Y2[u]; a[cnt].y=u; a[cnt].z=1; } sort(a+1,a+1+cnt,cmp2); /*for (int u=1;u<=cnt;u++) printf("%d %d %d\n",a[u].x,a[u].y,a[u].z);*/ bt(1,YY); int i=0; for (int u=1;u<=cnt;u++) { while (i+1<=a[u].x) { i++; change(1,X1[i],X2[i]); } ans=ans+a[u].z*get(1,a[u].y); } printf("%d\n",ans);}int main(){ init(); prepare(); solve(); return 0;}
发表评论
最新留言
留言是一种美德,欢迎回访!
[***.207.175.100]2025年03月20日 22时06分51秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
一个小例子对多态简单的理解
2019-03-06
poj 2187 Beauty Contest(凸包求解多节点的之间的最大距离)
2019-03-06
poj 2492A Bug's Life(并查集)
2019-03-06
ZZUOJ 1199 大小关系(拓扑排序,两种方法_判断入度和dfs回路判断)
2019-03-06
java中自动装箱的问题
2019-03-06
zyUpload+struct2完成文件上传
2019-03-06
knockout+echarts实现图表展示
2019-03-06