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

    1818: [CQOI2010]内部白点

    2017-08-25


     

    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

    这个题hzwer学长说想了一个小时
    于是我们开始想
    ……
    于是第二天我们开始找题解……
    …………
    于是第三天我们弃坑了x
    意外的很难搞……
    读入数据之后先离散一下,把10^9压到10^5
    接着把点分别按xy坐标排序,每两点建一条线
    这里有个玄学的技巧
    把竖着的线不当做线处理
    而是把两个端点看做两条长度为0的横线
    并分别给上下端点附上一个+1、-1的值k
    最后把边按y为第一关键字,k为第二关键字排序,遍历所有线
    维护一个树状数组
    对于竖线(端点),将树状数组对应的x位置+1或-1
    对于横线l~r,把答案加上树状数组中l~r-1的和(因为两端端点不加)
    这样全部扫一遍就可以了
     
    ……所以为什么不对啊
    调了好久还是没过……
    并不知道错哪了
    求dalao指点啊qwq
    附上错误代码
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int N=100009;
    struct node{int x,y;}a[N];
    struct segm{int l,r,y,k;}s[N];
    bool cmpx(node x,node y){if(x.x==y.x)return x.y<y.y;return x.x<y.x;}
    bool cmpy(node x,node y){if(x.y==y.y)return x.x<y.x;return x.y<y.y;}
    bool cmps(segm x,segm y){if(x.y==y.y)return x.k<y.k;return x.y<y.y;}
    int lowbit(int k){return k&(-k);}
    int n,cnt,ans,sum[N];
    void update(int k,int x)
    {
        while(k<=n)
        {
            sum[k]+=x;
            k+=lowbit(k);
        }
    }
    int found(int k)
    {
        int s=0;
        while(k)
        {
            s+=sum[k];
            k-=lowbit(k);
        }
        return s;
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;++i)scanf("%d%d",&a[i].x,&a[i].y);
    //    cout<<"discretization"<<endl;
        sort(a+1,a+n+1,cmpx);
        int l,r,tot=1,maxx=1,maxy=1;
        while(tot<=n){
            l=r=tot;
            while(a[l].x==a[r].x)r++;
            while(l<r)a[l].x=maxx,l++;
            maxx++,tot=r;
        }
        sort(a+1,a+n+1,cmpy);
        tot=1;
        while(tot<=n){
            l=r=tot;
            while(a[l].y==a[r].y)r++;
            while(l<r)a[l].y=maxy,l++;
            maxy++,tot=r;
        }    
    //    cout<<"addline"<<endl;
        for(int i=2;i<=n;++i)
        if(a[i].y==a[i-1].y)
        {
          ++cnt;
          s[cnt].l=a[i-1].x;
          s[cnt].r=a[i].x;
          s[cnt].y=a[i].y;
        }
        sort(a+1,a+n+1,cmpx);        
        for(int i=2;i<=n;++i)
        if(a[i].x==a[i-1].x)
        {
          ++cnt;
          s[cnt].l=s[cnt].r=a[i].x;
          s[cnt].y=a[i-1].y;
          s[cnt].k=1;
          ++cnt;
          s[cnt].l=s[cnt].r=a[i].x;
          s[cnt].y=a[i].y;
          s[cnt].k=-1;
        }
    //    cout<<"scan"<<endl;
        sort(s+1,s+cnt+1,cmps);
        for(int i=1;i<=cnt;++i)
        {
          int k=s[i].k;
          if(k==0)ans+=found(s[i].r-1)-found(s[i].l);
          else update(s[i].l,k);
        }
        cout<<ans+n<<endl;
        system("pause");
        return 0;
    }
    1818(wypx)(wa)

    by:wypx


    其实暴力什么的最神奇了的说♪

     

    思路:先以一个坐标轴找到每一个的最左&右的点,然后再这个图中加竖着的线,把线上的点记录一个bool数组,每一次扫横线上的被标记的个数,用n+这样找出的点就好了的说。O(∩_∩)O哈哈哈~(1e5的平方还是能接受的范围)
    by:s_a_b_e_r

    s:不想做题了,炉石什么的出橙卡的说,体现新卡的乐趣中.......
    w:到底哪不对啊QAQ(少女崩溃中)
  • 相关阅读:
    CSS HACK:IE6、IE7、IE8、Firefox兼容性问题解决方案
    C# @符号的多种使用方法
    16个Javascript的Web UI库、框架及工具包
    【分享】20个很不错的UI图标集资源
    JQuery/AjaX/Javascript/DIV+CSS资源下载地址
    发个csdn泄露账户查询地址,没下数据库的童鞋来查一下自己
    【总结】CSS透明度大汇总
    C#综合揭秘——细说事务
    ASP.NET获取客户端、服务器端基础信息集合
    收集的网络上大型的开源图像处理软件代码(提供下载链接)
  • 原文地址:https://www.cnblogs.com/ck666/p/7428159.html
Copyright © 2011-2022 走看看