zoukankan      html  css  js  c++  java
  • [HAOI2011]防线修建

    题意

    题目描述

    近来A国和B国的矛盾激化,为了预防不测,A国准备修建一条长长的防线,当然修建防线的话,肯定要把需要保护的城市修在防线内部了。可是A国上层现在还犹豫不决,到底该把哪些城市作为保护对象呢?又由于A国的经费有限,所以希望你能帮忙完成如下的一个任务:

    1. 给出你所有的A国城市坐标

    2. A国上层经过讨论,考虑到经济问题,决定取消对i城市的保护,也就是说i城市不需要在防线内了

    3. A国上层询问对于剩下要保护的城市,修建防线的总经费最少是多少

    你需要对每次询问作出回答。注意单位1长度的防线花费为1。

    A国的地形是这样的,形如下图,x轴是一条河流,相当于一条天然防线,不需要你再修建

    A国总是有两个城市在河边,一个点是(0,0),一个点是(n,0),其余所有点的横坐标均大于0小于n,纵坐标均大于0。A国有一个不在(0,0)和(n,0)的首都。(0,0),(n,0)和首都这三个城市是一定需要保护的。

    输入输出格式

    输入格式:

    第一行,三个整数n,x,y分别表示河边城市和首都是(0,0),(n,0),(x,y)。

    第二行,一个整数m。

    接下来m行,每行两个整数a,b表示A国的一个非首都非河边城市的坐标为(a,b)。

    再接下来一个整数q,表示修改和询问总数。

    接下来q行每行要么形如1 i,要么形如2,分别表示撤销第i个城市的保护和询问。

    输出格式:

    对于每个询问输出1行,一个实数v,表示修建防线的花费,保留两位小数

    输入输出样例

    输入样例#1: 复制
    4 2 1                                
    2                                 
    1 2                               
    3 2                               
    5                                 
    2
    1 1
    2
    1 2
    2
    输出样例#1: 复制
    6.47
    5.84
    4.47

    说明

    数据范围:

    30%的数据m<=1000,q<=1000

    100%的数据m<=100000,q<=200000,n>1

    所有点的坐标范围均在10000以内, 数据保证没有重点

    分析

    离线后倒过来做就是支持加点的动态凸包了。开局三个点,只维护上凸包,变量int范围内,出题人真良心。

    用平衡树(set)维护点集,插入的时候松弛一下就行了。

    时间复杂度(O(m log m + q))

    代码

    #include<bits/stdc++.h>
    #define rg register
    #define il inline
    #define co const
    template<class T>il T read(){
        rg T data=0,w=1;
        rg char ch=getchar();
        while(!isdigit(ch)){
            if(ch=='-') w=-1;
            ch=getchar();
        }
        while(isdigit(ch))
            data=data*10+ch-'0',ch=getchar();
        return data*w;
    }
    template<class T>il T read(rg T&x){
        return x=read<T>();
    }
    typedef long long ll;
    using namespace std;
    
    typedef struct Point{int x,y;}Vector;
    double dis(co Point&a,co Point&b) {return sqrt(pow(a.x-b.x,2)+pow(a.y-b.y,2));}
    bool operator<(co Point&a,co Point&b) {return a.x==b.x?a.y<b.y:a.x<b.x;}
    int operator/(co Vector&a,co Vector&b) {return a.x*b.y-a.y*b.x;}
    Vector operator-(co Vector&a,co Vector&b) {return (Vector){a.x-b.x,a.y-b.y};}
    set<Point> T;
    double sum;
    void insert(co Point&x){
    	set<Point>::iterator r=T.lower_bound(x),l=r,t;
    	if((*r-*(--l))/(x-*l)<0) return;
    	sum-=dis(*l,*r);
    	T.insert(x);
    	while(1){
    		t=r,r++;
    		if(r==T.end()) break;
    		if((*r-x)/(*t-x)>0) break;
    		sum-=dis(*t,*r);
    		T.erase(t);
    	}
    	while(l!=T.begin()){
    		t=l,l--;
    		if((*t-x)/(*l-x)>0) break;
    		sum-=dis(*t,*l);
    		T.erase(t);
    	}
    	T.insert(x);
    	l=r=t=T.find(x);
    	--l,++r;
    	sum+=dis(*l,x)+dis(*r,x);
    }
    
    co int N=1e5+1;
    int n,m,q,mark[N];
    Point p[N];
    struct operation {int o,i;}opt[N*2];
    double ans[N*2];
    int main(){
    //	freopen(".in","r",stdin),freopen(".out","w",stdout);
    	read(n),read(p[0].x),read(p[0].y);
    	T.insert((Point){0,0}),T.insert((Point){n,0}),T.insert(p[0]);
    	sum+=dis((Point){0,0},p[0])+dis((Point){n,0},p[0]);
    	read(m);
    	for(int i=1;i<=m;++i) read(p[i].x),read(p[i].y);
    	read(q);
    	for(int i=1;i<=q;++i){
    		read(opt[i].o);
    		if(opt[i].o==1) mark[read(opt[i].i)]=1;
    	}
    	for(int i=1;i<=m;++i) if(!mark[i]) insert(p[i]);
    	for(int i=q;i>=1;--i){
    		if(opt[i].o==1) insert(p[opt[i].i]);
    		else ans[i]=sum;
    	}
    	for(int i=1;i<=q;++i) if(opt[i].o==2)
    		printf("%.2lf
    ",ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    积水路面Wet Road Materials 2.3
    门控时钟问题
    饮料机问题
    Codeforces Round #340 (Div. 2) E. XOR and Favorite Number (莫队)
    Educational Codeforces Round 82 (Rated for Div. 2)部分题解
    Educational Codeforces Round 86 (Rated for Div. 2)部分题解
    Grakn Forces 2020部分题解
    2020 年百度之星·程序设计大赛
    POJ Nearest Common Ancestors (RMQ+树上dfs序求LCA)
    算法竞赛进阶指南 聚会 (LCA)
  • 原文地址:https://www.cnblogs.com/autoint/p/10533821.html
Copyright © 2011-2022 走看看