BZOJ 2300[HAOI2011]防线修建

题面:

2300: [HAOI2011]防线修建

Time Limit: 10 Sec  Memory Limit: 512 MB
Submit: 960  Solved: 527
[Submit][Status][Discuss]

Description

近来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)和首都这三个城市是一定需要保护的。

上图中,A,B,C,D,E点为A国城市,且目前都要保护,那么修建的防线就会是A-B-C-D,花费也就是线段AB的长度+线段BC的长度+线段CD的长度,如果,这个时候撤销B点的保护,那么防线变成下图 

Input

第一行,三个整数n,x,y分别表示河边城市和首都是(0,0),(n,0),(x,y)。
第二行,一个整数m。
接下来m行,每行两个整数a,b表示A国的一个非首都非河边城市的坐标为(a,b)。
再接下来一个整数q,表示修改和询问总数。
接下来q行每行要么形如1 i,要么形如2,分别表示撤销第i个城市的保护和询问。

Output

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

Sample Input

4 2 1
2
1 2
3 2
5
2
1 1
2
1 2
2

Sample Output

6.47
5.84
4.47

HINT

m<=100000,q<=200000,n>1

所有点的坐标范围均在10000以内, 数据保证没有重点
 
将询问离线后就变成支持插入操作的动态凸包,用set维护。
  1 #include<stdio.h>
  2 #include<math.h>
  3 #include<set>
  4 #include<iostream>
  5 using namespace std;
  6 #define maxn 100001
  7 #define maxm 200001
  8 struct QAQ
  9 {
 10     int x,y;
 11     friend QAQ operator - (QAQ a,QAQ b)
 12     {
 13         return (QAQ){a.x-b.x,a.y-b.y};
 14     }
 15     friend int operator * (QAQ a,QAQ b)
 16     {
 17         return a.x*b.y-b.x*a.y;
 18     }
 19     bool operator < (const QAQ &a) const
 20     {
 21         return x<a.x||(x==a.x&&y<a.y);
 22     }
 23 }T_T[maxn];
 24 struct QWQ
 25 {
 26     double ans;
 27     int op,x;
 28 }TAT[maxm];
 29 bool book[maxn];
 30 int n,m;
 31 double ans;
 32 double dis(QAQ a,QAQ b)
 33 {
 34     return sqrt(1.0*(a.x-b.x)*(a.x-b.x)+1.0*(a.y-b.y)*(a.y-b.y));
 35 }
 36 set<QAQ>ss;
 37 void insert(int p,int q)
 38 {
 39     QAQ t=(QAQ){p,q};
 40     set<QAQ>::iterator r=ss.lower_bound(t),l=r,s;
 41     l--;
 42     if((*r-*l)*(t-*l)<0)
 43         return ;
 44     ans-=dis(*l,*r);
 45     while(1)
 46     {
 47         s=r;
 48         r++;
 49         if(r==ss.end())
 50             break;
 51         if((*r-t)*(*s-t)>0)
 52             break;
 53         ans-=dis(*r,*s);
 54         ss.erase(s);
 55     }
 56     while(l!=ss.begin())
 57     {
 58         s=l;
 59         l--;
 60         if((*s-t)*(*l-t)>0)
 61             break;
 62         ans-=dis(*s,*l);
 63         ss.erase(s);
 64     }
 65     ss.insert(t);
 66     l=r=s=ss.find(t);
 67     l--,r++;
 68     ans+=dis(*l,*s)+dis(*r,*s);
 69 }
 70 int main()
 71 {
 72     int a,b,T;
 73     QAQ t1,t2,t3;
 74     scanf("%d%d%d",&n,&a,&b);
 75     t1=(QAQ){0,0};
 76     t2=(QAQ){n,0};
 77     t3=(QAQ){a,b};
 78     ss.insert(t1);
 79     ss.insert(t2);
 80     ss.insert(t3);
 81     scanf("%d",&T);
 82     ans+=dis(t1,t3)+dis(t2,t3);
 83     for(int i=1;i<=T;i++)
 84         scanf("%d%d",&T_T[i].x,&T_T[i].y);
 85     scanf("%d",&m);
 86     for(int i=1;i<=m;i++)
 87     {
 88         scanf("%d",&TAT[i].op);
 89         if(TAT[i].op==1)
 90         {
 91             scanf("%d",&TAT[i].x);
 92             book[TAT[i].x]=true;
 93         }
 94     }
 95     for(int i=1;i<=T;i++)
 96         if(!book[i])
 97             insert(T_T[i].x,T_T[i].y);
 98     for(int i=m;i>=1;i--)
 99     {
100         if(TAT[i].op==1)
101             insert(T_T[TAT[i].x].x,T_T[TAT[i].x].y);
102         else
103             TAT[i].ans=ans;
104     }
105     for(int i=1;i<=m;i++)
106         if(TAT[i].op==2)
107             printf("%.2lf\n",TAT[i].ans);
108 }
BZOJ 2300
 
posted @ 2017-08-08 07:07  avancent  阅读(139)  评论(0编辑  收藏  举报