BZOJ [HAOI2011]防线修建(动态凸包)

听说有一种很高端的东西叫动态凸包维护dp就像学一下,不过介于本人还不会动态凸包就去学了下,还是挺神奇的说,维护上下凸包的写法虽然打得有点多不过也只是维护复制黏贴的事情而已罢了。

先说下动态凸包怎么写吧,搞棵平衡树存上下凸壳然后每次插入一个点就往他左右维护看是否满足凸性否则就弹出,就是这么简单

这道题就是删点然后询问凸壳,那么离线反着做就行了

出题人还是挺良心的直接让你维护上凸壳就行了,还不用管边界条件

用set打了一下,比较慢但还是挺好打的= =

换新blog挺多功能得试试的,现在想搞个像HZWER的那个球还有一个虾米等有时间试试(当然还有头像!!!)

好了不多说了发完睡觉了= =

CODE:

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<set>
 6 #include<cmath>
 7 using namespace std;
 8 typedef pair<int,int> ii;
 9 typedef set<ii>::iterator iter;
10 #define fi first
11 #define se second
12 #define sqr(x) ((x)*(x))
13 inline double dist(ii u,ii v) {return sqrt(sqr(u.fi-v.fi)+sqr(u.se-v.se));}
14 inline int cross(ii x,ii y,ii z) {
15     return (y.fi-x.fi)*(z.se-x.se)-(y.se-x.se)*(z.fi-x.fi);
16 }
17 set<ii> gap;
18 #define maxn 201000
19 int a[maxn][2],c[maxn][2];
20 bool b[maxn];
21 double sum,ans[maxn];
22 inline void del(iter x){
23     iter u=x,v=x;
24     u--,v++;
25     sum-=dist(*u,*x)+dist(*x,*v);
26     sum+=dist(*u,*v);
27     gap.erase(x);
28 }
29 inline void ins(ii x){
30     iter it=gap.upper_bound(x);
31     --it;
32     iter v=it,u;++v;
33     if (cross(*it,x,*v)>=0) return;
34     gap.insert(x);
35     it=gap.find(x);
36     v=it,u=it;
37     --u,++v;
38     sum+=dist(*u,*it)+dist(*it,*v);
39     sum-=dist(*u,*v);
40     for (iter v=it,u;;v=it){
41         ++v;u=v;++v;
42         if (v==gap.end()) break;
43         if (cross(*it,*u,*v)<0) break;
44         del(u);
45     }
46     for (iter v=it,u;;v=it){
47         --v;
48         if (v==gap.begin()) break;
49         u=v;--v;
50         if (cross(*v,*u,*it)<0) break;
51         del(u);
52     }
53 }
54 int main(){
55     int n,m,q;
56     scanf("%d%d%d",&n,&a[0][0],&a[0][1]);
57     scanf("%d",&m);
58     for (int i=1;i<=m;i++) scanf("%d%d",a[i],a[i]+1);
59     scanf("%d",&q);
60     for (int i=1;i<=q;i++) {
61         scanf("%d",c[i]);
62         if (c[i][0]==1) scanf("%d",c[i]+1),b[c[i][1]]=1;
63     }
64     gap.insert(ii(0,0));
65     gap.insert(ii(n,0));
66     sum=n;
67     for (int i=0;i<=m;i++) if (!b[i]) ins(ii(a[i][0],a[i][1]));
68     for (int i=q;i;i--) {
69         if (c[i][0]==1) ins(ii(a[c[i][1]][0],a[c[i][1]][1]));
70         else ans[i]=sum;
71     }
72     for (int i=1;i<=q;i++)
73         if (ans[i]) printf("%.2lf\n",ans[i]);
74     return 0;
75 }
时间: 2024-08-07 12:25:01

BZOJ [HAOI2011]防线修建(动态凸包)的相关文章

【题解】P2521 [HAOI2011]防线修建(动态凸包)

[题解]P2521 [HAOI2011]防线修建(动态凸包) 凸包是易插入不好删除的东西,按照剧情所以我们时光倒流 然后问题就是维护凸包的周长,支持加入 本来很简单,但是计算几何就是一些小地方经验不足容易WA和RE 然后代码注释里有一些经验 //@winlere #include<iostream> #include<set> #include<cstdio> #include<cstring> #include<algorithm> #incl

BZOJ 2300: [HAOI2011]防线修建( 动态凸包 )

离线然后倒着做就变成了支持加点的动态凸包...用平衡树维护上凸壳...时间复杂度O(NlogN) ----------------------------------------------------------------------- #include<cmath> #include<cstdio> #include<cctype> #include<cstring> #include<cstdlib> #include<algori

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

给定 \(n\) 个点,有 \(m\) 次操作,每次指定一个点将其删去,或询问当前上凸包的周长.有 \((0,0),(n,0),(x,y)\) 三个点不会被删去,且所有点的 \(x\) 坐标都位于 \((0,n)\),所有点的 \(y\) 坐标都位于 \((0,+\infty)\) Solution 逆序处理,就是一个动态凸包的裸题 注意可能会有重复,要先处理一下 有些没被删过的点要提前先加进去 #include <bits/stdc++.h> using namespace std; con

【BZOJ 2300】 2300: [HAOI2011]防线修建 (动态凸包+set)

2300: [HAOI2011]防线修建 Description 近来A国和B国的矛盾激化,为了预防不测,A国准备修建一条长长的防线,当然修建防线的话,肯定要把需要保护的城市修在防线内部了.可是A国上层现在还犹豫不决,到底该把哪些城市作为保护对象呢?又由于A国的经费有限,所以希望你能帮忙完成如下的一个任务: 1.给出你所有的A国城市坐标 2.A国上层经过讨论,考虑到经济问题,决定取消对i城市的保护,也就是说i城市不需要在防线内了 3.A国上层询问对于剩下要保护的城市,修建防线的总经费最少是多少

bzoj千题计划236:bzoj2300: [HAOI2011]防线修建

http://www.lydsy.com/JudgeOnline/problem.php?id=2300 维护动态凸包,人懒用的set 用叉积判断,不要用斜率 #include<set> #include<cmath> #include<cstdio> #include<iostream> using namespace std; #define N 100001 struct node { int x,y; node(int x_=0,int y_=0):

【BZOJ2300】[HAOI2011]防线修建 set维护凸包

[BZOJ2300][HAOI2011]防线修建 Description 近来A国和B国的矛盾激化,为了预防不测,A国准备修建一条长长的防线,当然修建防线的话,肯定要把需要保护的城市修在防线内部了.可是A国上层现在还犹豫不决,到底该把哪些城市作为保护对象呢?又由于A国的经费有限,所以希望你能帮忙完成如下的一个任务: 1.给出你所有的A国城市坐标 2.A国上层经过讨论,考虑到经济问题,决定取消对i城市的保护,也就是说i城市不需要在防线内了 3.A国上层询问对于剩下要保护的城市,修建防线的总经费最少

Luogu-2521 [HAOI2011]防线修建

倒过来处理所有询问,就变成了一道动态凸包的裸题 吐槽一下这道题只要维护上凸壳就好了,我zz了没好好看题打了两个2333 // luogu-judger-enable-o2 #include<set> #include<cmath> #include<cstdio> #include<cstring> #include<algorithm> #define rp (*r) #define lp (*l) #define rrp (*rr) #def

HAOI2011 防线修建

题目链接:戳我 动态维护凸包的题目qwqwq 30分还是很好写的..直接一个凸包就完事了 代码如下: #include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<algorithm> #include<cmath> #define MAXN 100010 using namespace std; int n,nx,ny,m,q,o

BZOJ 2300 HAOI 2011 防线修建 动态维护凸包

题目大意:一些成熟分布在第一象限中,现在要建造一个防线来保护他们,但是随着时间的推移,必须要舍弃一些城市,但是不会舍弃首都.问最短的防线需要多长. 思路:在每一个时刻求一个上凸包就是答案了.当然这样做时间复杂度就呵呵了.考虑一下动态维护凸包.因为只有上凸包,所以处理起来会相对方便.我们只需把在凸包中的点按照x坐标排序,然后二分一下把点插入凸包,然后左右用斜率维护一下,这样每次插点的时间复杂度大概是O(logn).但是这样只能插点不能删点,所以离线处理一下,把删点转化为插点,最后倒着输出. (我比