zoukankan      html  css  js  c++  java
  • B1818 [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

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<ctime>
    #include<queue>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    #define duke(i,a,n) for(int i = a;i <= n;i++)
    #define lv(i,a,n) for(int i = a;i >= n;i--)
    #define clean(a) memset(a,0,sizeof(a))
    const int INF = 1 << 30;
    typedef long long ll;
    typedef double db;
    template <class T>
    void read(T &x)
    {
        char c;
        bool op = 0;
        while(c = getchar(), c < '0' || c > '9')
            if(c == '-') op = 1;
        x = c - '0';
        while(c = getchar(), c >= '0' && c <= '9')
            x = x * 10 + c - '0';
        if(op) x = -x;
    }
    template <class T>
    void write(T x)
    {
        if(x < 0) putchar('-'), x = -x;
        if(x >= 10) write(x / 10);
        putchar('0' + x % 10);
    }
    struct point
    {
        int x,y;
    }a[100010];
    struct seg
    {
        int k,x,y,r;
    }s[1000010];
    int n;
    int hsh[100010],cnt = 0;
    int tr[100010],ans = 0;
    bool cmp1(point a,point b)
    {
        if(a.x == b.x)
        return a.y < b.y;
        else
        return a.x < b.x;
    }
    bool cmp2(point a,point b)
    {
        if(a.y == b.y)
        return a.x < b.x;
        else
        return a.y < b.y;
    }
    bool cmp3(seg a,seg b)
    {
        if(a.y == b.y)
        return a.k < b.k;
        else
        return a.y < b.y;
    }
    int find(int x)
    {
        int l = 1,r = n,mid;
        while(l <= r)
        {
            int mid = (l + r) >> 1;
            if(hsh[mid] < x)
            l = mid + 1;
            else if(hsh[mid] > x)
            r = mid - 1;
            else return mid;
        }
    }
    void insert(int k,int l,int r,int t)
    {
        if(!k)
        {
            s[++cnt].x = find(l);
            s[cnt].r = find(r);
            s[cnt].y = t;
        }
        else
        {
            s[++cnt].x = find(t);
            s[cnt].y = l;
            s[cnt].k = 1;
            s[++cnt].x = find(t);
            s[cnt].y = r;
            s[cnt].k = -1;
        }
    }
    int lowbit(int x)
    {
        return x & -x;
    }
    void build()
    {
        sort(a + 1,a + n + 1,cmp1);
        duke(i,2,n)
        {
            if(a[i].x == a[i - 1].x)
            insert(1,a[i - 1].y,a[i].y,a[i].x);
        }
        sort(a + 1,a + n + 1,cmp2);
        duke(i,2,n)
        {
            if(a[i].y == a[i - 1].y)
            insert(0,a[i - 1].x,a[i].x,a[i].y);
        }
    }
    void update(int x,int y)
    {
        while(x <= n)
        {
            tr[x] += y;
            x += lowbit(x);
        }
    }
    int ask(int x)
    {
        int s = 0;
        while(x)
        {
            s += tr[x];
            x -= lowbit(x);
        }
        return s;
    }
    void work()
    {
        duke(i,1,cnt)
        {
            if(!s[i].k)
            ans += ask(s[i].r - 1) - ask(s[i].x);
            else
            update(s[i].x,s[i].k);
        }
    }
    int main()
    {
        read(n);
        duke(i,1,n)
        {
            read(a[i].x);
            read(a[i].y);
            hsh[i] = a[i].x;
        }
        sort(hsh + 1,hsh + n + 1);
        build();
        sort(s + 1,s + cnt + 1,cmp3);
        work();
        printf("%d
    ",ans + n);
        return 0;
    }
    /*
    4
    0 2
    2 0
    -2 0
    0 -2
    */
  • 相关阅读:
    angularjs $index用来取顺序
    angularjs &登录跳转
    if(!confirm("您确定删除吗?")){return;}
    登录跳转
    undefined null测试
    git生成密钥
    遍历map
    网络相关名词解释
    redis的Pub/Sub
    SQLAlchemy的使用
  • 原文地址:https://www.cnblogs.com/DukeLv/p/9753792.html
Copyright © 2011-2022 走看看