• 【BZOJ2300】【HAOI2011】防线修建


    题目大意:给你m+3个点,有q个操作,每次要么询问当前点集构所构成的上凸壳总长度,要么在当前点集中删除一个点。

    这题是吼题啊!!!

    刚开始想着如何正常地做,考虑过用线段树维护一个区间内的凸包,发现并不行,要另请高明。

    后来发现,这题并没有强制在线要求,我们不妨将所有的询问反过来处理。首先将从头到尾都没有被删除的点加入该凸包,然后将询问倒序处理,将原先的删点操作改为加点操作,随后动态维护该凸包并维护上凸壳总长度,需输出的答案压入一个栈中,最后逐个弹出输出即可。

    至于如何动态维护凸包。本题有一个很特殊的条件:所有点坐标的x,y值均大于0,且必有一个点坐标为(0,0)。故我们可以用一个set维护当前在凸包上的点,当需要加入一个点k时,借助lower_bound找到与该点相邻夹角的两个点,直接进行维护即可。实现细节较为复杂,强烈建议先工整地将维护方法写在草稿纸上!!

    PS:这次发现set容器的iterator有一些神奇的性质,假定有一个迭代器指针it,其后继为it1,在it未更新时,若有一个元素插入在it和it1之间,那么it1仍将认为其后继为it1而非新插入的元素,需要用某些方法更新下it(没有1a的元凶)

     1 #include<bits/stdc++.h>
     2 #define M 210000
     3 using namespace std;
     4 struct node{
     5     int x,y; node(){x=y=0;}
     6     node(int xx,int yy){x=xx; y=yy;}
     7     friend node operator -(node a,node b){return node(a.x-b.x,a.y-b.y);}
     8     friend int operator *(node a,node b){
     9         return a.y*b.x-a.x*b.y;
    10     }
    11     friend bool operator <(node a,node b){
    12         if(a.x==0&&a.y==0) return 0; 
    13         if(b.x==0&&b.y==0) return 1;
    14         if(a.x*b.y==a.y*b.x) return a.x<b.x;
    15         return a.y*b.x<a.x*b.y;
    16     }
    17 }a[M];
    18 set<node> s;
    19 
    20 int n,x,y,m,op[M]={0},id[M]={0}; bool vis[M]={0};
    21 int cj(node a,node b,node c){return (b-a)*(c-a);}
    22 double dis(node a,node b){return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}
    23 double ans=0;
    24 
    25 void ins(node k){
    26     set<node>::iterator now,nowm,nown,pre;
    27     nown=nowm=now=s.upper_bound(k);
    28     now--; nowm--; nowm--;
    29     while(cj(*nowm,*now,k)>0){
    30         ans=ans-dis(*nown,*now)-dis(*now,*nowm)+dis(*nown,*nowm);
    31         pre=now; *now--; 
    32         s.erase(pre);
    33         if(nowm==s.begin()) break;
    34         *nowm--; 
    35     }
    36     if(cj(*now,k,*nown)>0) return;
    37     ans=ans-dis(*nown,*now)+dis(*nown,k)+dis(*now,k);
    38     s.insert(k);
    39     nowm=now=nown=s.find(k);
    40     now++; nown++; nown++;
    41     while(cj(*nowm,*now,*nown)>0&&nown!=s.end()){
    42         ans=ans-dis(*nown,*now)-dis(*now,*nowm)+dis(*nown,*nowm);
    43         pre=now; *now++; *nown++;
    44         s.erase(pre);
    45     }
    46 }
    47 double ansp[M]={0};int use=0;
    48 int main(){
    49     scanf("%d%d%d",&n,&x,&y);
    50     s.insert(node(0,0)); s.insert(node(n,0)); s.insert(node(x,y));
    51     ans=dis(node(0,0),node(x,y))+dis(node(x,y),node(n,0));
    52     scanf("%d",&n);
    53     for(int i=1;i<=n;i++) scanf("%d%d",&a[i].x,&a[i].y);
    54     scanf("%d",&m);
    55     for(int i=1;i<=m;i++){
    56         scanf("%d",op+i);
    57         if(op[i]==2) continue;
    58         scanf("%d",id+i);
    59         vis[id[i]]=1;
    60     }
    61     for(int i=1;i<=n;i++) if(!vis[i]) ins(a[i]);
    62     for(int i=m;i;i--){
    63         if(op[i]==2) {ansp[++use]=ans; continue;}
    64         if(!vis[id[i]]) continue;
    65         ins(a[id[i]]); vis[id[i]]=0;
    66     }
    67     while(use) printf("%.2lf
    ",ansp[use--]);
    68 }
  • 相关阅读:
    IOI 1996 网络协议
    lougu P2344奶牛抗议
    Poj3764 The XOR-longest Path
    A Simple Problem with Integers (线段树)
    NOIP2011 选择客栈
    20181029 T3 乐谱分段
    20181029 T2 寻宝游戏
    20181029 T1 教科书般的亵渎
    NOIP2011聪明的质监员
    浅谈AC自动机
  • 原文地址:https://www.cnblogs.com/xiefengze1/p/7886853.html
Copyright © 2020-2023  润新知