zoukankan      html  css  js  c++  java
  • LOJ6049 拍苍蝇

    拍苍蝇

    有一天,小A的母亲对他家里的卫生状况非常不满意,他的房间里有非常多的苍蝇。在母亲的威逼利诱下,小A拿起了苍蝇拍去消灭家里的苍蝇。然而,小A以前从来没有亲手消灭过任何一只苍蝇,以至于在他拿起苍蝇拍的那一刻,他对苍蝇起了怜悯之心 —— 他不想伤害任何一只苍蝇。现在,小A面前的窗户上有(N)只苍蝇,他想知道有多少种方式可以在他拿起苍蝇拍拍窗户的时候,不伤害任何一只苍蝇。

    窗户可以看作是一个左下角位于坐标系原点的矩形,苍蝇拍可以看作是一个多边形。在小A向窗户挥苍蝇拍时,对应多边形的顶点必须位于坐标系的整点上,并且苍蝇拍所在位置不能超过窗户所在范围。一只苍蝇会被伤害当且仅当小A用苍蝇拍拍向窗户时,苍蝇位于苍蝇拍内部、边上或顶点上。

    题解

    考虑bitset。如果我们能求出苍蝇拍上有哪些整点,那么直接枚举苍蝇拍放的位置然后判定整点跟苍蝇无交即可。时间复杂度(O(frac{X^4}{64}))

    问题转化成如何求苍蝇拍上的整点,这是个经典扫描线问题。由于数据范围很小,所以我们可以暴力枚举横坐标,然后对纵坐标进行排序。每经过一条边,在内部/在外部的状态就会翻转。注意特判多边形的边竖直的情况。时间复杂度(O(XKlog K)),当然这是跑不满的。

    CO int N=510,M=1e5+10;
    struct point {int x,y;} p[M];
    bitset<N> fly[N],swat[N];
    int val[N][N];
    
    int main(){
    	int Xp=read<int>(),Yp=read<int>();
    	for(int n=read<int>();n--;){
    		int x=read<int>(),y=read<int>();
    		fly[x][y]=1;
    	}
    	int K=read<int>();
    	int Xl=1e9,Xr=-1e9,Yl=1e9,Yr=-1e9;
    	for(int i=1;i<=K;++i){
    		read(p[i].x),read(p[i].y);
    		Xl=min(Xl,p[i].x),Xr=max(Xr,p[i].x),Yl=min(Yl,p[i].y),Yr=max(Yr,p[i].y);
    	}
    	Xr-=Xl,Yr-=Yl;
    	for(int i=1;i<=K;++i){
    		p[i].x-=Xl,p[i].y-=Yl;
    		swat[p[i].x][p[i].y]=1;
    	}
    	for(int x=0;x<=Xr;++x){
    		vector<float128> stk;
    		for(int i=1;i<=K;++i){
    			point a=p[i],b=p[i%K+1];
    			if(a.y>b.y) swap(a,b);
    			if((a.x<x and b.x<x) or (a.x>x and b.x>x)) continue;
    			if((a.x==x and b.x>x) or (b.x==x and a.x>x)) continue; // count it only once
    			if(a.x==x and b.x==x){
    				for(int y=a.y+1;y<=b.y-1;++y) swat[x][y]=1;
    				continue;
    			}
    			stk.push_back((float128)(b.y-a.y)/(b.x-a.x)*(x-a.x)+a.y);
    		}
    		sort(stk.begin(),stk.end());
    		for(int y=0,i=0,flag=0;y<=Yr;++y){
    			for(;i<(int)stk.size() and stk[i]<y;++i) flag^=1; // inside or outside
    			if(flag or (i<(int)stk.size() and stk[i]==y)) swat[x][y]=1;
    		}
    	}
    	for(int x=0;x<=Xp-Xr;++x) fill(val[x],val[x]+Yp-Yr+1,1);
    	for(int i=0;i<=Xr;++i)for(int y=0;y<=Yp-Yr;++y){
    		CO bitset<N>&now=swat[i]<<y;
    		for(int x=0;x<=Xp-Xr;++x)
    			if(val[x][y] and (now&fly[x+i]).any()) val[x][y]=0;
    	}
    	int ans=0;
    	for(int x=0;x<=Xp-Xr;++x) ans+=accumulate(val[x],val[x]+Yp-Yr+1,0);
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    Spring security中的BCryptPasswordEncoder方法对密码进行加密与密码匹配
    Eclipse导入SpringBoot项目pom.xml第一行报错Unknown error
    分库分表理论概述
    什么是乐观锁,什么是悲观锁
    oracle中的索引查看
    手动实现tail
    KNN理论
    矩阵以及向量
    numpy常用的几个小函数
    线性回归
  • 原文地址:https://www.cnblogs.com/autoint/p/12838183.html
Copyright © 2011-2022 走看看