zoukankan      html  css  js  c++  java
  • P5816 [CQOI2010]内部白点

    题目描述

    无限大正方形网格里有 nn 个黑色的顶点,所有其他顶点都是白色的(网格的顶点即坐标为整数的点,又称整点)。每秒钟,所有内部白点同时变黑,直到不存在内部白点为止。你的任务是统计最后网格中的黑点个数。

    内部白点的定义:一个白色的整点 P(x,y) 是内部白点当且仅当 PP 在水平线的左边和右边各至少有一个黑点(即存在x_1 < x < x_2 使得 (x_1 , y) 和 (x_2 , y) 都是黑点),且在竖直线的上边和下边各至少有一个黑点(即存在 y_1 < y < y_2 使得 (x,y_1) 和 (x,y_2)) 都是黑点)。

    输入格式

    输入第一行包含一个整数 n,即初始黑点个数。

    以下 nn 行每行包含两个整数 x,y,即一个黑点的坐标。没有两个黑点的坐标相同,坐标的绝对值均不超过 10^9 。

    输出格式

    输出仅一行,包含黑点的最终数目。

    如果变色过程永不终止,输出-1。

    输入输出样例

    输入 #1复制

    4
    0 2
    2 0
    -2 0
    0 -2

    输出 #1复制

    5

    说明/提示

    数据范围

    对于 36% 的数据,n≤500。
    对于 64% 的数据,n≤3×10^4 。
    对于 100% 的数据,n≤10^5 。

    一个很坑的事实是不会有-1的情况,为啥?(你puts("-1")试试啊

    其实是因为,一个点能否变成黑点与他上下左右四个点有关,准确的说是和最上面,最左面,。。的有关。
    而一个点他被其他点变成了黑色,那肯定是有比他靠左,比他靠上。。。的(。。。自行脑补,我太懒了)

    然后把横坐标相同的连一块,纵坐标相同的连一块。
    像这样(图是ez_lcw巨佬的)

    然后扫描线解决。。
    将x离散化,按y排序,从下往上扫。。具体的看代码吧,各位巨佬肯定能看懂

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<vector>
    #include<cmath>
    #include<queue>
    #include<set>
    #include<map>
    using namespace std;
    typedef long long LL;
    const int N = 1e5+10;
    inline int read()
    {
        register int x = 0 , f = 0; register char c = getchar();
        while(c < '0' || c > '9') f |= c == '-' , c = getchar();
        while(c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0' , c = getchar();
        return f ? -x : x;
    }
    int n;
    int a[N];
    struct point{ int x , y; }p[N];
    struct Line{ int val , x , y , z; }s[N * 3];
    inline bool cmp(const Line &A , const Line &B) { return A.y == B.y ? A.val < B.val : A.y < B.y; }
    inline bool cmpx(const point &A , const point &B) { return A.x == B.x ? A.y < B.y : A.x < B.x; }
    inline bool cmpy(const point &A , const point &B) { return A.y == B.y ? A.x < B.x : A.y < B.y; }
    
    namespace BIT
    {
    	LL tr[N];
    	void Add(int pos , int val) { if(pos <= 0) return ; while(pos <= n) tr[pos] += val , pos += (pos & (-pos)); return ; }
    	LL Ask(int pos) { if(pos <= 0) return 0LL; LL ans = 0LL; while(pos) ans += tr[pos] , pos -= (pos & (-pos)); return ans; }
    }
    
    int main()
    {
    	n = read();
    	for(int i = 1 ; i <= n ; ++i) a[i] = p[i].x = read() , p[i].y = read();
    	sort(a + 1 , a + 1 + n); int tot = unique(a + 1 , a + 1 + n) - a - 1;
    	for(int i = 1 ; i <= n ; ++i) p[i].x = lower_bound(a + 1 , a + 1 + tot , p[i].x) - a;
    	sort(p + 1 , p + 1 + n , cmpx); tot = 0;
    	for(int i = 2 ; i <= n ; ++i) 
    		if(p[i].x == p[i-1].x) 
    			s[++tot].val = 1 , s[tot].x = p[i].x , s[tot].y = p[i-1].y , 
    			s[++tot].val = -1 , s[tot].x = p[i].x , s[tot].y = p[i].y;
    	sort(p + 1 , p + 1 + n , cmpy);
    	for(int i = 2 ; i <= n ; ++i)
    		if(p[i].y == p[i-1].y)
    			s[++tot].val = 0 , s[tot].x = p[i-1].x , s[tot].z = p[i].x , s[tot].y = p[i].y;
    	sort(s + 1 , s + 1 + tot , cmp);
    	using namespace BIT;
    	LL ans = n;
    	for(int i = 1 ; i <= tot ; ++i)
    		if(s[i].val) Add(s[i].x , s[i].val); else ans += Ask(s[i].z - 1) - Ask(s[i].x); // 不包括两端 
    	cout << ans << '
    ';
    	return 0;
    }
    
  • 相关阅读:
    弹性布局----Flex
    mysql多实例双主部署
    你知道你的类是从什么地方加载来的吗?
    ElasticSearch学习,入门篇(一)
    Spring声明式事物原理分析
    SpringBoot启动流程分析
    Spring Aop 原理分析
    Spring容器的创建原理
    你可能不知道的jvm的类加载机制
    面向工资编程的程序员,后来都过得怎么样。
  • 原文地址:https://www.cnblogs.com/R-Q-R-Q/p/12691768.html
Copyright © 2011-2022 走看看