zoukankan      html  css  js  c++  java
  • bzoj 1818: [Cqoi2010]内部白点

    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

    Source

    题目看起来吓人且鬼畜,但是其实答案过了1s之后就不会变了;

    这个可以画一下图,如果某个方向缺了一个点,导致他不能变黑的话,那么这个方向上也不可能有点变黑了,从而他也不可能变黑,所以在1s之后答案确定;

    那么接下的问题就是一个扫描线的经典问题了,由于我们在计数的时候不能把原来的黑点也算进去,所以我们取横竖线段的时候要两两断开;

    扫描线的具体做法是,通过sort求出所有横线和竖线,然后把竖线拆为两条,从下往上扫描,

    遇到竖线的下端点就给该竖线的横坐标+1,遇到上端点就-1,然后遇到横线就查询一下横坐标范围内的权值和;

    通过树状数组实现单点修改和区间查询,注意在纵坐标相同时,优先级为撤销>查询>添加;

    //MADE BY QT666
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    typedef long long ll;
    const int N=500050;
    int n,hsh[N],tot,tmp;
    struct data{
        int x,y;
    }g[N];
    bool cmp1(const data &a,const data &b){
        if(a.x==b.x) return a.y<b.y;
        else return a.x<b.x;
    }
    bool cmp2(const data &a,const data &b){
        if(a.y==b.y) return a.x<b.x;
        else return a.y<b.y;
    }
    struct date{
        int l,r,x,y,op;
    }q[N];
    int find(int x){return lower_bound(hsh+1,hsh+1+tot,x)-hsh;}
    bool cmp3(const date &a,const date &b){
        if(a.y==b.y) return a.op<b.op;
        else return a.y<b.y;
    }
    int tr[N];
    int lowbit(int x){return x&-x;}
    void update(int x,int v){
        for(int i=x;i<=tot;i+=lowbit(i)) tr[i]+=v;
    }
    int query(int x){
        int ret=0;if(x==0) return 0;
        for(int i=x;i;i-=lowbit(i)) ret+=tr[i];
        return ret;
    }
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
    	scanf("%d%d",&g[i].x,&g[i].y);
    	hsh[++tot]=g[i].x;
        }
        sort(hsh+1,hsh+1+tot);tot=unique(hsh+1,hsh+1+tot)-hsh-1;
        sort(g+1,g+1+n,cmp1);
        for(int i=2;i<=n;i++){
    	if(g[i].x==g[i-1].x){
    	    tmp++;q[tmp].x=find(g[i-1].x),q[tmp].y=g[i-1].y,q[tmp].op=1;
    	    tmp++;q[tmp].x=find(g[i].x),q[tmp].y=g[i].y,q[tmp].op=-1;
    	}
        }
        sort(g+1,g+1+n,cmp2);
        for(int i=2;i<=n;i++){
    	if(g[i].y==g[i-1].y){
    	    tmp++;q[tmp].l=find(g[i-1].x),q[tmp].r=find(g[i].x),q[tmp].y=g[i].y,q[tmp].op=0;
    	}
        }
        sort(q+1,q+1+tmp,cmp3);int sum=0;
        for(int i=1;i<=tmp;i++){
    	if(q[i].op==1) update(q[i].x,1);
    	if(q[i].op==-1) update(q[i].x,-1);
    	if(q[i].op==0) sum+=query(q[i].r-1)-query(q[i].l);
        }
        printf("%d
    ",sum+n);
        return 0;
    }
    
  • 相关阅读:
    POJ 3710 Christmas Game#经典图SG博弈
    POJ 2599 A funny game#树形SG(DFS实现)
    POJ 2425 A Chess Game#树形SG
    LeetCode Array Easy 122. Best Time to Buy and Sell Stock II
    LeetCode Array Easy121. Best Time to Buy and Sell Stock
    LeetCode Array Easy 119. Pascal's Triangle II
    LeetCode Array Easy 118. Pascal's Triangle
    LeetCode Array Easy 88. Merge Sorted Array
    ASP.NET MVC 学习笔记之 MVC + EF中的EO DTO ViewModel
    ASP.NET MVC 学习笔记之面向切面编程与过滤器
  • 原文地址:https://www.cnblogs.com/qt666/p/7662234.html
Copyright © 2011-2022 走看看