• Bzoj2300 / 洛谷P2521 [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以内, 数据保证没有重点

    数学问题 计算几何 凸包

    由于下边不用考虑,实际上我们只需要维护一个上凸壳。

    离线询问,倒序加点,如果新加入的点在凸壳下面,就无视它,如果在凸壳上面,就将它加入凸壳,并删除原凸壳上的无用点。

    凸壳上的点集可以用set或者平衡树维护。

    倒序加点的时候忘了把没被删过的点先加进去,WA了一发

      1 #include<algorithm>
      2 #include<iostream>
      3 #include<cstring>
      4 #include<cstdio>
      5 #include<cmath>
      6 #include<vector>
      7 #include<set>
      8 using namespace std;
      9 const double eps=1e-7;
     10 const int mxn=200010;
     11 int read(){
     12     int x=0,f=1;char ch=getchar();
     13     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     14     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
     15     return x*f;
     16 }
     17 struct point{
     18     double x,y;
     19     point operator + (point b){return (point){x+b.x,y+b.y};}
     20     point operator - (point b){return (point){x-b.x,y-b.y};}
     21     double operator * (point b){return x*b.x+y*b.y;}
     22     bool operator < (point b)const{
     23         return x<b.x || (x==b.x && y<b.y);
     24     }
     25 }a[mxn];
     26 int cnt=0;
     27 double Cross(point a,point b){
     28     return a.x*b.y-a.y*b.x;
     29 }
     30 double dist(point a,point b){
     31     return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
     32 }
     33 struct query{
     34     int id,tp;
     35 }q[mxn];
     36 struct cmp{bool operator () (const int c,const int d){return a[c].x<a[d].x;}};
     37 set<int,cmp>st;
     38 double nowans,ans[mxn];
     39 int top=0;
     40 void solve(int x){
     41     set<int,cmp>::iterator it,iL,iR;
     42     it=st.lower_bound(x);
     43     iL=it;iL--;
     44     int L=*iL,R=*it;
     45     if(Cross(a[x]-a[L],a[R]-a[x])>0)return;//在已有凸壳内
     46     nowans-=dist(a[L],a[R]);
     47     while(1){
     48         R=*it;it++;
     49         if(it==st.end())break;
     50         if(Cross(a[R]-a[x],a[*it]-a[x])>0){
     51             nowans-=dist(a[R],a[*it]);
     52             st.erase(R);
     53         }
     54         else break;
     55     }
     56     while(1){
     57         if(iL==st.begin())break;
     58         L=*iL;iL--;
     59         if(Cross(a[L]-a[*iL],a[x]-a[*iL])>0){
     60             nowans-=dist(a[*iL],a[L]);
     61             st.erase(L);
     62         }
     63         else break;
     64     }
     65     st.insert(x);
     66     it=st.find(x);
     67     iL=it;iL--;iR=it;iR++;
     68     nowans+=dist(a[*iL],a[x])+dist(a[x],a[*iR]);
     69     return;
     70 }
     71 bool vis[mxn];
     72 int n,m,Q;
     73 int main(){
     74 //    freopen("defense.in","r",stdin);
     75 //    freopen("defense.out","w",stdout);
     76     int i,j,x,y;
     77     n=read();x=read();y=read();
     78     a[++cnt]=(point){0,0};a[++cnt]=(point){n,0};a[++cnt]=(point){x,y};
     79     st.insert(1);st.insert(2);st.insert(3);
     80     nowans+=dist(a[2],a[3])+dist(a[1],a[3]);
     81     m=read();
     82     for(i=1;i<=m;i++){
     83         ++cnt;
     84         a[cnt].x=read();a[cnt].y=read();
     85     }
     86     Q=read();
     87     for(i=1;i<=Q;i++){
     88         q[i].tp=read();
     89         if(q[i].tp==1) q[i].id=read(),vis[q[i].id]=1;
     90     }
     91     for(i=1;i<=m;i++){
     92         if(!vis[i])solve(i+3);
     93     }
     94     for(i=Q;i;i--){
     95         if(q[i].tp==2){
     96             ans[++top]=nowans;
     97             continue;
     98         }
     99         solve(q[i].id+3);
    100     }
    101     while(top){
    102         printf("%.2f
    ",ans[top--]);
    103     }
    104     return 0;
    105 }
  • 相关阅读:
    说说渐进式增强
    Websocket模板
    Echart图表显示单位
    JS配置文件设置,共享变量抽取
    PHP处理字符串的10个简单方法
    C#实现只许一个实例运行(使用mutex类)
    实现PHP基本安全11条
    PHP开发不能违背的安全规则
    Querying a motor position
    log info
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/6668903.html
Copyright © 2020-2023  润新知