码迷,mamicode.com
首页 > 其他好文 > 详细

[HAOI2011] 防线修建 - 动态凸包,set

时间:2020-03-01 19:35:31      阅读:64      评论:0      收藏:0      [点我收藏+]

标签:mes   lin   裸题   ase   指定   凸包   solution   auto   ble   

给定 \(n\) 个点,有 \(m\) 次操作,每次指定一个点将其删去,或询问当前上凸包的周长。有 \((0,0),(n,0),(x,y)\) 三个点不会被删去,且所有点的 \(x\) 坐标都位于 \((0,n)\),所有点的 \(y\) 坐标都位于 \((0,+\infty)\)

Solution

逆序处理,就是一个动态凸包的裸题

注意可能会有重复,要先处理一下

有些没被删过的点要提前先加进去

#include <bits/stdc++.h>
using namespace std;

const int N = 200005;

struct point {
    int x,y;
    point(){}
    point(int a,int b){x=a;y=b;}
    bool operator != (const point &a) const {return (x!=a.x)||(y!=a.y);};
    bool operator < (const point &a) const {return (x==a.x)?(y<a.y):(x<a.x);}
    point operator - (const point &a) const {return point(x-a.x,y-a.y);}
    int operator * (const point &a) const {return x*a.y-y*a.x;}
} p[N];

double dis(point a,point b) {return sqrt(pow(a.x-b.x,2)+pow(a.y-b.y,2));}
set<point> s;
double ans;
int n;

void add(point p) {
    point a,b,c;
    auto it=s.upper_bound(p);
    b=*it;
    --it;
    a=*it;
    if(p.x==b.x || (p-a)*(b-p)>=0) return;
    ans-=dis(a,b);
    while(a!=(point){0,0}) {
        it--; c=*it;
        if((a-c)*(p-a)>=0) {
            ans-=dis(a,c);
            s.erase(s.find(a));
            a=c;
        }
        else break;
    }
    it=s.find(b);
    while(b!=(point){n,0}) {
        it++; c=*it;
        if((b-p)*(c-b)>=0) {
            ans-=dis(b,c);
            s.erase(s.find(b));
            b=c;
        }
        else break;
    }
    ans+=dis(a,p)+dis(p,b);
    s.insert(p);
}

int m,q,x[N],y[N],X,Y,fg[N];
vector <double> o;

signed main() {
    cin>>n>>X>>Y>>m;
    s.insert({0,0});
    s.insert({n,0});
    s.insert({X,Y});
    ans=dis((point){0,0},(point){X,Y})+dis((point){n,0},(point){X,Y});
    for(int i=1;i<=m;i++) {
        cin>>p[i].x>>p[i].y;
    }
    cin>>q;
    for(int i=1;i<=q;i++) {
        cin>>x[i];
        if(x[i]==1) {
            cin>>y[i];
            if(fg[y[i]]==0) {
                fg[y[i]]=1;
            }
            else x[i]=0;
        }
    }
    for(int i=1;i<=m;i++) if(fg[i]==0) add(p[i]);
    for(int i=q;i>=1;--i) {
        if(x[i]==1) {
            add(p[y[i]]);
        }
        if(x[i]==2) {
            o.push_back(ans);
        }
    }
    while(o.size()) printf("%.2lf\n",o.back()), o.pop_back();
}

[HAOI2011] 防线修建 - 动态凸包,set

标签:mes   lin   裸题   ase   指定   凸包   solution   auto   ble   

原文地址:https://www.cnblogs.com/mollnn/p/12391425.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!