1. 程式人生 > 其它 >題解 P2521 [HAOI2011]防線修建

題解 P2521 [HAOI2011]防線修建

Solution

實際上不需要使用set或平衡樹來維護凸包 , 使用連結串列即可 .
我們記錄每個點在整張圖上的前點和後點和在凸包上的前點和後點 , 對於刪除操作我們在連結串列上刪除這個點 , 如果它在凸包上 , 那麼重構它在凸包上的前後之間的區域並動態維護凸包周長 .

Code

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
int read()
{
    int ret=0;char c=getchar();
    while(c>'9'||c<'0')c=getchar();
    while(c>='0'&&c<='9')ret=(ret<<3)+(ret<<1)+(c^48),c=getchar();
    return ret;
}
const int maxn=1e5+5;
int n,m;
struct point
{
    int x,y;int ord;
    const bool operator <(const point &a)const{if(x!=a.x)return x<a.x;return y<a.y;}
    const point operator -(const point &a)const{return point{x-a.x,y-a.y};}
    const int operator *(const point &a)const{return x*a.y-a.x*y;}
    friend double dis(point &a,point &b){return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}
}p[maxn];
int pre[maxn],nxt[maxn];
int cpre[maxn],cnxt[maxn];
bool used[maxn];
int sta[maxn],top;
double ans;
int num[maxn];
void andrew(int l,int r)
{
    top=0;sta[++top]=l;
    for(int i=nxt[l];i<=r;i=nxt[i])
    {
        while(top>=2&&(p[sta[top]]-p[sta[top-1]])*(p[i]-p[sta[top]])>=0)used[sta[top--]]=0;
        used[i]=1;
        sta[++top]=i;
    }
    for(int i=1;i<top;i++)ans+=dis(p[sta[i]],p[sta[i+1]]);
    for(int i=1;i<=top;i++)
    {
        if(i!=1)cpre[sta[i]]=sta[i-1];
        if(i!=top)cnxt[sta[i]]=sta[i+1];
    }
}
int main()
{
    p[2].x=read();p[3].x=read();p[3].y=read();
    n=read()+3;
    for(int i=4;i<=n;i++)p[i].x=read(),p[i].y=read(),p[i].ord=i-3;
    sort(p+1,p+n+1);
    for(int i=1;i<=n;i++)num[p[i].ord]=i;
    for(int i=1;i<=n;i++)pre[i]=i-1,nxt[i]=i+1;
    andrew(1,n);
    m=read();
    while(m--)
    {
        int opt=read();
        if(opt==1)
        {
            int x=read();
            x=num[x];
            pre[nxt[x]]=pre[x];
            nxt[pre[x]]=nxt[x];
            if(!used[x])continue;
            ans-=dis(p[cpre[x]],p[x])+dis(p[cnxt[x]],p[x]);
            andrew(cpre[x],cnxt[x]);
        }
        else if(opt==2)printf("%.2lf\n",ans);
    }
    return 0;
}