题目大意:一些成熟分布在第一象限中,现在要建造一个防线来保护他们,但是随着时间的推移,必须要舍弃一些城市,但是不会舍弃首都。问最短的防线需要多长。
思路:在每一个时刻求一个上凸包就是答案了。当然这样做时间复杂度就呵呵了。考虑一下动态维护凸包。因为只有上凸包,所以处理起来会相对方便。我们只需把在凸包中的点按照x坐标排序,然后二分一下把点插入凸包,然后左右用斜率维护一下,这样每次插点的时间复杂度大概是O(logn)。但是这样只能插点不能删点,所以离线处理一下,把删点转化为插点,最后倒着输出。
(我比较懒,然后为省去平衡树直接上set了,可恶的iterator不支持+1,写的这个DT。。。
CODE:
#include <set> #include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 200010 #define EPS 1e-10 using namespace std; struct Operation{ int flag,p; void Read() { scanf("%d",&flag); if(flag == 1) scanf("%d",&p); } }opt[MAX]; struct Point{ int x,y; Point(int _ = 0,int __ = 0):x(_),y(__) {} bool operator <(const Point &a)const { if(x == a.x) return y < a.y; return x < a.x; } void Read() { scanf("%d%d",&x,&y); } }point[MAX]; set<Point> convex; set<Point>::iterator first,last; int cnt,asks; int x,y,n; bool ban[MAX]; double ans[MAX]; double length; inline double Calc(const Point &a,const Point &b) { return sqrt((double)(a.x - b.x) * (a.x - b.x) + (double)(a.y - b.y) * (a.y - b.y)); } inline double GetSlope(const Point &a,const Point &b) { if(a.x == b.x) return 1e15; return (double)(b.y - a.y) / (b.x - a.x); } inline void Insert(const Point &p) { set<Point>::iterator it = convex.insert(p).first; set<Point>::iterator _it = --it; ++it; set<Point>::iterator __it = first; if(_it != first) { __it = --_it; ++_it; } set<Point>::iterator it_ = ++it; --it; set<Point>::iterator it__ = last; if(it_ != last) { it__ = ++it_; --it_; } if(GetSlope(*_it,*it) > GetSlope(*it,*it_)) length -= Calc(*_it,*it_); else { convex.erase(it); return ; } while(_it != first && GetSlope(*__it,*_it) < GetSlope(*_it,*it)) { length -= Calc(*_it,*__it); convex.erase(_it); _it = __it--; } while(it_ != last && GetSlope(*it,*it_) < GetSlope(*it_,*it__)) { length -= Calc(*it_,*it__); convex.erase(it_); it_ = it__++; } length += Calc(*it,*_it) + Calc(*it,*it_); } int main() { cin >> n >> x >> y; first = convex.insert(Point(0,0)).first; convex.insert(Point(x,y)); last = convex.insert(Point(n,0)).first; length = Calc(Point(x,y),Point(0,0)) + Calc(Point(x,y),Point(n,0)); cin >> cnt; for(int i = 1; i <= cnt; ++i) point[i].Read(); cin >> asks; for(int i = 1; i <= asks; ++i) { opt[i].Read(); ban[opt[i].p] = true; } for(int i = 1; i <= cnt; ++i) if(!ban[i]) Insert(point[i]); for(int i = asks; i; --i) { if(opt[i].flag == 1) Insert(point[opt[i].p]); else ans[i] = length; } for(int i = 1; i <= asks; ++i) if(fabs(ans[i]) > EPS) printf("%.2lf\n",ans[i]); return 0; }