• bzoj 2300 [HAOI2011]防线修建 set动态维护凸包


    题目大意

    动态删点,求凸包周长

    分析

    反过来变成动态加点
    用set维护平衡树
    具体是找到凸包上左右两点
    拆开
    就可以把左边当作顺时针求的一个凸包,右边当作逆时针求的一个凸包,像栈那样出set就好了
    注意新点在凸包内不用管它
    每个点进一次出一次
    (O(n log n))

    solution

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <cctype>
    #include <algorithm>
    #include <set>
    using namespace std;
    typedef double db;
    const db eps=1e-7;
    const int M=200007;
    
    inline int rd(){
    	int x=0;bool f=1;char c=getchar();
    	for(;!isdigit(c);c=getchar()) if(c=='-') f=0;
    	for(;isdigit(c);c=getchar()) x=x*10+c-48;
    	return f?x:-x;
    }
    
    db sum;
    int n,m;
    int kd[M],opr[M];
    bool vis[M];
    db ans[M];
    
    struct pt{
    	db x,y;
    	pt(db _x=0.0,db _y=0.0){x=_x; y=_y;}
    }p[M];
    /*精度已经把我搞啥了我都不知道加不加,加了set直接炸
    bool eq(db x,db y){return fabs(x-y)<=eps;}
    bool neq(db x,db y){return !eq(x,y);}
    bool le(db x,db y){return eq(x,y)||x<y;}
    bool ge(db x,db y){return eq(x,y)||x>y;}
    */
    pt operator -(pt x,pt y){return pt(x.x-y.x,x.y-y.y);}
    pt operator +(pt x,pt y){return pt(x.x+y.x,x.y+y.y);}
    pt operator *(pt x,db d){return pt(x.x*d,x.y*d);}
    pt operator /(pt x,db d){return pt(x.x/d,x.y/d);}
    bool operator <(pt x,pt y){if(x.x!=y.x)return x.x<y.x;return x.y<y.y;}
    
    db dot(pt x,pt y){
    	return x.x*y.x+x.y*y.y;
    }
    
    db cross(pt x,pt y){
    	return x.x*y.y-x.y*y.x;
    }
    
    db area(pt x,pt y,pt z){
    	return cross(y-x,z-x);
    }
    
    db length(pt x){
    	return sqrt(dot(x,x));
    }
    
    set<pt>S;
    typedef set<pt>::iterator its;
    
    void gao(pt x){
    	its r=S.lower_bound(x);
    	its l=r; --l;
    	if(area(*l,x,*r)>=0) return;//凸包内
    	sum-=length(*r-*l);
    	its tp;
    	while(1){
    		tp=r;
    		++r;
    		if(r==S.end()) break;
    		if(area(*r,*tp,x)<=0){
    			sum-=length(*tp-*r);
    			S.erase(tp);
    		}
    	}
    	while(1){
    		if(l==S.begin()) break;
    		tp=l;
    		--l;
    		if(area(*l,*tp,x)>=0){
    			sum-=length(*tp-*l);
    			S.erase(tp);
    		}
    		else break;
    	}
    	S.insert(x);
    	l=r=S.find(x);
    	l--; r++;
    	sum+=length(x-*l);
    	sum+=length(x-*r);
    }
    
    int main(){
    	int i,z,x,y;
    	
    	z=rd(),x=rd(),y=rd();
    	
    	pt nw=pt(0,0);
    	S.insert(nw);
    	
    	nw=pt(z,0);
    	S.insert(nw);
    	
    	nw=pt(x,y);
    	S.insert(nw);
    	
    	sum=length(pt(x,y))+length(pt(z-x,y));
    	
    	n=rd();
    	for(i=1;i<=n;i++){
    		x=rd(),y=rd();
    		p[i]=pt(x,y);
    	}
    	
    	m=rd();
    	for(i=1;i<=m;i++){
    		kd[i]=rd();
    		if(kd[i]==1){
    			opr[i]=rd();
    			vis[opr[i]]=1;
    		}
    	}
    	
    	for(i=1;i<=n;i++)
    		if(!vis[i]) gao(p[i]);
    		
    	for(i=m;i>0;i--){
    		if(kd[i]==2) ans[i]=sum;
    		else gao(p[opr[i]]);
    	}
    	
    	for(i=1;i<=m;i++) if(kd[i]==2) printf("%.2lf
    ",ans[i]);
    	
    	return 0;
    }
    
  • 相关阅读:
    兄弟连,一般人来不起,来的肯定不是一般人!
    50天之脱变,66期第一个项目感受。切记平常心
    2016十大影响事件
    为什么要写年终总结
    20161228阅读笔记
    为什么要认识牛人
    李笑来:演讲能力是我这一生有幸学到的最重要能力
    张辉:工作几年就应该给自己“清零”
    小马宋:目标决定方法~坚持目标而不是方法
    李笑来的财务自由法~把一份时间卖出很多份
  • 原文地址:https://www.cnblogs.com/acha/p/6431758.html
Copyright © 2020-2023  润新知