• 【BZOJ1818】【CQOI2010】 内部白点


    内部白点

    题意

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

    你的任务是统计最后网格中的黑点个数。 内部白点的定义:一个白色的整点P(x,y)是内部白点当且仅当P在水平线的左边和右边各至少有一个黑点(即存在x1 < x < x2使得(x1,y)和(x2,y)都是黑点),且在竖直线的上边和下边各至少有一个黑点(即存在y1 < y < y2使得(x,y1)和(x,y2)都是黑点)。如果变色过程永不终止,输出-1。

    (由于原本题意就很简明,所以我就不简述了)

    Solution

    显然不可能永不终止,因为白点变成黑点当且仅当白点在两条黑点线的交点上,也就是在黑点线上,这样以来黑点线的数量是不会变的。

    所以考虑线离散化一遍坐标,然后树状数组差分维护一下,类似于扫描线的过程。

    首先我们把全部与x轴垂直的线段找出来,然后我们找与y轴垂直的线段,在这个线段的左端点打上1的标记,右端点打上-1的标记,按照x坐标扫过去,遇见这些点我们就修改一下树状数组,然后一个线段就区间查询就好了。树状数组某一位代表的是y坐标,遇到右端点时线段在修改后就相当于被去掉了。

    #include<bits/stdc++.h>
    using namespace std;
    inline int lowbit(int x){return x&-x;}
    int c[200010];
    int n;
    void update(int x,int v){
    	while(x<=n){
    		c[x]+=v;
    		x+=lowbit(x);
    	}
    }
    int query(int x){
    	int ans=0;
    	while(x){
    		ans+=c[x];
    		x-=lowbit(x);
    	}
    	return ans;
    }
    struct node{
    	int x,y;
    }a[200010];
    bool cmp1(node a,node b){
    	return a.x==b.x?(a.y<b.y):a.x<b.x;
    }
    bool cmp2(node a,node b){
    	return a.y==b.y?(a.x<b.x):a.y<b.y;
    }
    int xxx[200010],yyy[200010];
    int cnt1,cnt2;
    map<int,int>mp1,mp2;
    struct xline{
    	int l,r;
    	int x;
    }l1[200010];
    int tot1;
    struct point{
    	int x,y;
    	int type;
    }p[200010];
    int tot2;
    bool cmp(point a,point b){
    	return a.x==b.x?(a.y<b.y):a.x<b.x;
    }
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;++i){
    		scanf("%d%d",&a[i].x,&a[i].y);
    		xxx[i]=a[i].x,yyy[i]=a[i].y;
    	}
    	sort(xxx+1,xxx+1+n);
    	sort(yyy+1,yyy+1+n);
    	for(int i=1;i<=n;++i){
    		if(mp1[xxx[i]]==0)mp1[xxx[i]]=++cnt1;
    		if(mp2[yyy[i]]==0)mp2[yyy[i]]=++cnt2;
    	}
    	for(int i=1;i<=n;++i){
    		a[i].x=mp1[a[i].x];
    		a[i].y=mp2[a[i].y];
    	}
    	sort(a+1,a+1+n,cmp1);
    	for(int i=1;i<n;++i){
    		if(a[i].x==a[i+1].x){
    			l1[++tot1].x=a[i].x;
    			l1[tot1].l=a[i].y;
    			l1[tot1].r=a[i+1].y;
    		}
    	}
    	sort(a+1,a+1+n,cmp2);
    	for(int i=1;i<n;++i){
    		if(a[i].y==a[i+1].y){
    			p[++tot2].x=a[i].x,p[tot2].y=a[i].y,p[tot2].type=1;
    			p[++tot2].x=a[i+1].x,p[tot2].y=a[i+1].y,p[tot2].type=-1;
    		}
    	}
    	int ans=0;
    	int ttt=1;
    	sort(p+1,p+1+tot2,cmp);
    	for(int i=1;i<=tot1;++i){
    		if(l1[i].x!=l1[i-1].x)
    		for(int j=l1[i-1].x;j<=l1[i].x;++j){
    			while(j==p[ttt].x){
    				update(p[ttt].y,p[ttt].type);
    				++ttt;
    			}
    		}
    		ans+=(query(l1[i].r-1)-query(l1[i].l));
    	}
    	printf("%d
    ",ans+n);
    }
    
  • 相关阅读:
    Sa提权sql语句大全
    转载 使用AJAX实现动态刷新页面功能
    VirtualBox宿主机与虚拟机的数据共享数据空间
    SP_OACreate提权经验
    linux mysql启动错误
    Microsoft SQL Server SA权限最新入侵方法 不用net user添加账户
    Java中关于HashMap的使用和遍历
    转载 突破360防黑加固添加用户
    个人随想BLOG
    面试题收集
  • 原文地址:https://www.cnblogs.com/youddjxd/p/11620708.html
Copyright © 2020-2023  润新知