[luogu P2521] [HAOI2011]防线修建

题目描述

近来A国和B国的矛盾激化,为了预防不测,A国准备修建一条长长的防线,当然修建防线的话,肯定要把需要保护的城市修在防线内部了。可是A国上层现在还犹豫不决,到底该把哪些城市作为保护对象呢?又由于A国的经费有限,所以希望你能帮忙完成如下的一个任务:

  1. 给出你所有的A国城市坐标

  2. A国上层经过讨论,考虑到经济问题,决定取消对i城市的保护,也就是说i城市不需要在防线内了

  3. A国上层询问对于剩下要保护的城市,修建防线的总经费最少是多少

你需要对每次询问作出回答。注意单位1长度的防线花费为1。

A国的地形是这样的,形如下图,x轴是一条河流,相当于一条天然防线,不需要你再修建

A国总是有两个城市在河边,一个点是(0,0),一个点是(n,0),其余所有点的横坐标均大于0小于n,纵坐标均大于0。A国有一个不在(0,0)和(n,0)的首都。(0,0),(n,0)和首都这三个城市是一定需要保护的。

(别瞅了,luogu没有图)

输入输出格式

输入格式:

第一行,三个整数n,x,y分别表示河边城市和首都是(0,0),(n,0),(x,y)。

第二行,一个整数m。

接下来m行,每行两个整数a,b表示A国的一个非首都非河边城市的坐标为(a,b)。

再接下来一个整数q,表示修改和询问总数。

接下来q行每行要么形如1 i,要么形如2,分别表示撤销第i个城市的保护和询问。

输出格式:

对于每个询问输出1行,一个实数v,表示修建防线的花费,保留两位小数

输入输出样例

输入样例#1: 复制

4 2 1
2
1 2
3 2
5
2
1 1
2
1 2
2

输出样例#1: 复制

6.47
5.84
4.47

说明

数据范围:

30%的数据m<=1000,q<=1000

100%的数据m<=100000,q<=200000,n>1

所有点的坐标范围均在10000以内, 数据保证没有重点

想了好久,也码了好久。刚开始没有想到时光倒流,往cdq去想了。平衡树也很难操作。

最后看了发题解——艹,怎么又没想到时光倒流!

时光倒流以后,就相当于维护一个支持单点更新的上凸包,并求周长-n。

还好题目限制好了,不然要烦死、、

那我们采取这样的方法:

插入一个点时,先判断在不在凸包内。如果不在,则向两边维护一个凸包,直到不能删点或者符合一个凸包时停止。

其中判断是否在凸包内,通过找两个点,一个前驱,一个后缀,都在凸包边上。

其中,设当前插入点为c,前缀为u,后缀为v,满足u.x<c.x||u.x==c.x&&u.y<c.y,v.x>c.x||v.x==c.x&&v.y>c.y。

如果cross(c-u,v-u)>0(cross表示两个向量叉积),则说明c在凸包内。

否则向两边维护更新凸壳。

根据对称性,我们只取向左边的进行研究。

设u为凸包上c的前缀,v为凸包上u的前缀。

当然如果u(0,0),那么就退出了,(0,0)是不能删的。

否则如果cross(c-v,u-v)>0,则维护好了,退出,否则就删了u,继续。

至此,维护单点更新成功了,且复杂度正确,因为,每个点最多插入一次,删除一次。

其中求pre,suc可以看做是连带的,换句话说,次数和删除操作次数差不多(倍数在常数级)。

这里的复杂度大致就是nlogn基本的。

但是同样,我们会有一个棘手的问题->计算周长。

如果每次找凸包上每个点的前驱后缀计算感觉会很慢,也很难写。

如果我们在删点,加点时就计算,是不是就比较快呢?

不过要注意,不要漏删一条边或多加一条边,细节还是有点的。

还有,其中前驱后缀插入删除都是平衡树的操作。

(splay比stl快?无意抢了luogu'rank1,233)

code:

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 #include <cmath>
  5 #define ms(a,x) memset(a,x,sizeof a)
  6 using namespace std;
  7
  8 void OJ() {
  9     #ifndef ONLINE_JUDGE
 10         freopen("in.txt","r",stdin);
 11         freopen("out.txt","w",stdout);
 12     #endif
 13 }
 14 namespace fastIO {
 15     #define gec(c) getchar(c)
 16     #define puc(c) putchar(c)
 17     char ch;
 18     inline int read() {
 19         int x=0,f=1; ch=getchar();
 20         while (ch<'0'||ch>'9') {
 21             if (ch=='-') f=-f;
 22             ch=gec();
 23         }
 24         while (ch>='0'&&ch<='9') {
 25             x=(x<<3)+(x<<1)+ch-'0';
 26             ch=getchar();
 27         }
 28         return x*f;
 29     }
 30 } using namespace fastIO;
 31
 32 const int N=200005;
 33 int n,m,q,las;
 34 bool vis[N]; double ans[N];
 35 struct query {
 36     int t,x;
 37 } o[N];
 38
 39 #define SplayTree node
 40 struct SplayTree {
 41     int X,Y;
 42     node* c[3];
 43     node () {
 44         X=Y=0;
 45         c[0]=c[1]=c[2]=0;
 46     }
 47 } * ro,* g,* U,* V,* re;
 48
 49 #define vec city
 50 struct city {
 51     int x,y;
 52     city () {}
 53     city (int _x,int _y) :
 54         x(_x),y(_y) {};
 55     city (node* u) :
 56         x(u->X),y(u->Y) {};
 57 } a[N];
 58 int cross (vec u,vec v) {
 59     return u.x*v.y-u.y*v.x;
 60 }
 61 vec operator - (city u,city v) {
 62     return vec(u.x-v.x,u.y-v.y);
 63 }
 64 node* noded (city u) {
 65     node* rt=new node();
 66     rt->X=u.x,rt->Y=u.y;
 67     return rt;
 68 }
 69 void setup (node* &x,int X,int Y) {
 70     x=new node(),x->X=X,x->Y=Y;
 71 }
 72 bool dir (node* x) {
 73     if (!x->c[2]) return 0;
 74     return x->c[2]->c[1]==x;
 75 }
 76 void linknode (node* y,node* x,bool p) {
 77     if (x) x->c[2]=y;
 78     if (y) y->c[p]=x;
 79 }
 80 void rotate (node* x) {
 81     bool p=dir(x); node* y=x->c[2];
 82     linknode(y->c[2],x,dir(y));
 83     linknode(y,x->c[p^1],p);
 84     linknode(x,y,p^1);
 85 }
 86 void splay (node* x,node* an) {
 87     if (x->c[2]==an) return;
 88     while (x->c[2]!=an) {
 89         if (x->c[2]->c[2]==an) {
 90             rotate(x);
 91             if (!an) ro=x;
 92             return;
 93         }
 94         rotate(dir(x)^dir(x->c[2])?x:x->c[2]);
 95         rotate(x);
 96     }
 97     if (!an) ro=x;
 98 }
 99 bool cmp (node* u,node* v) {
100     return u->X==v->X?u->Y<v->Y:u->X<v->X;
101 }
102 void insert (node* &x,node* u) {
103     if (!x) {
104         g=x=u;
105         return;
106     }
107     bool p=cmp(x,u);
108     insert(x->c[p],u),x->c[p]->c[2]=x;
109 }
110 void erase (node* u) {
111     splay(u,0);
112     if (!ro->c[0]||!ro->c[1]) {
113         if (ro->c[0]) ro=ro->c[0],ro->c[2]=0; else
114         if (ro->c[1]) ro=ro->c[1],ro->c[2]=0; else
115         ro=0;
116         return;
117     }
118     for (re=ro->c[0]; re->c[1]; re=re->c[1]) ;
119     splay(re,ro);
120     re->c[2]=0,re->c[1]=ro->c[1];
121     if (re->c[1]) re->c[1]->c[2]=re;
122     ro=re;
123 }
124 bool cmp_1 (node* u,node* v) {
125     return u->X==v->X?u->Y<v->Y:u->X<v->X;
126 }
127 bool cmp_2 (node* u,node* v) {
128     return u->X==v->X?u->Y>v->Y:u->X>v->X;
129 }
130 void pre (node* x,node* u) {
131     if (!x) return;
132     if (cmp_1(x,u)) re=x,pre(x->c[1],u);
133     else pre(x->c[0],u);
134 }
135 void suc (node* x,node* u) {
136     if (!x) return;
137     if (cmp_2(x,u)) re=x,suc(x->c[0],u);
138     else suc(x->c[1],u);
139 }
140 #define sqr(x) ((x)*(x))
141 double dis (node* u,node* v) {
142     return sqrt(sqr(u->X-v->X)+sqr(u->Y-v->Y));
143 }
144 void maintain () {
145     pre(ro,g),U=re,suc(ro,g),V=re;
146     if (cross(city(g)-city(U),city(V)-city(U))>0) return;
147     if (U->X!=0||U->Y!=0||V->X!=n||V->Y!=0) ans[0]-=dis(U,V);
148     for ( ; ; ) {
149         pre(ro,g),U=re;
150         if (U->X==0&&U->Y==0) {
151             ans[0]+=dis(g,U);
152             break;
153         }
154         pre(ro,U),V=re;
155         if (cross(city(g)-city(V),city(U)-city(V))>0) {
156             ans[0]+=dis(g,U);
157             break;
158         }
159         ans[0]-=dis(U,V);
160         erase(U);
161     }
162     for ( ; ; ) {
163         suc(ro,g),U=re;
164         if (U->X==n&&U->Y==0) {
165             ans[0]+=dis(g,U);
166             break;
167         }
168         suc(ro,U),V=re;
169         if (cross(city(g)-city(V),city(U)-city(V))<0) {
170             ans[0]+=dis(g,U);
171             break;
172         }
173         ans[0]-=dis(U,V);
174         erase(U);
175     }
176     insert(ro,g);
177     splay(g,0);
178 }
179
180 int main() {
181     OJ();
182     n=read(),a[0].x=read(),a[0].y=read();
183     m=read(),a[m+1]=city(0,0),a[m+2]=city(n,0);
184     for (int i=1; i<=m; ++i) {
185         a[i].x=read(),a[i].y=read();
186     }
187     ms(vis,1);
188     q=read();
189     for (int i=1; i<=q; ++i) {
190         o[i].t=read();
191         if (o[i].t&1) o[i].x=read();
192         vis[o[i].x]=0;
193     }
194     ro=0;
195     insert(ro,noded(a[0]));
196     insert(ro,noded(a[m+1]));
197     insert(ro,noded(a[m+2]));
198     ans[0]=dis(noded(a[0]),noded(a[m+1]))+dis(noded(a[0]),noded(a[m+2]));
199     for (int i=1; i<=m; ++i) {
200         if (vis[i]) g=noded(a[i]),maintain();
201     }
202     for (int i=q; i; --i) {
203         if (o[i].t&1) g=noded(a[o[i].x]),maintain();
204         else ans[i]=ans[0];
205     }
206     for (int i=1; i<=q; ++i) {
207         if (~o[i].t&1) printf("%.2lf\n",ans[i]);
208     }
209     return 0;
210 }

View Code

转载于:https://www.cnblogs.com/whc200305/p/7944307.html

[luogu P2521] [HAOI2011]防线修建相关推荐

  1. Bzoj2300 / 洛谷P2521 [HAOI2011]防线修建

    题目描述 近来A国和B国的矛盾激化,为了预防不测,A国准备修建一条长长的防线,当然修建防线的话,肯定要把需要保护的城市修在防线内部了.可是A国上层现在还犹豫不决,到底该把哪些城市作为保护对象呢?又由于 ...

  2. P2521 [HAOI2011]防线修建

    传送门 一眼看出可以倒着做转为加点维护凸包,然后--然后我就不会了-- 看了一眼题解,大概是这样的,我们先把所有点都读进来,然后按极角排序,也就是说定义点的大小为他们极角的大小(本题里实际上直接按x坐 ...

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

    [BZOJ2300][HAOI2011]防线修建 Description 近来A国和B国的矛盾激化,为了预防不测,A国准备修建一条长长的防线,当然修建防线的话,肯定要把需要保护的城市修在防线内部了.可 ...

  4. 【bzoj2300】【Luogu P2521】 [HAOI2011]防线修建 动态凸包,平衡树,Set

    一句话题意:给你一个凸包,每次可以插入一个点或者询问周长. 动态凸包裸题嘛,用\(Set\)实现.最初每个点坐标做乘三处理,便于取初始三角形的重心作为凸包判定原点. #include <bits ...

  5. [bzoj2300] [HAOI2011]防线修建

    Description 近来A国和B国的矛盾激化,为了预防不测,A国准备修建一条长长的防线,当然修建防线的话,肯定要把需要保护的城市修在防线内部了.可是A国上层现在还犹豫不决,到底该把哪些城市作为保护 ...

  6. cogs 547:[HAOI2011] 防线修建

    ★★★☆   输入文件:defense.in   输出文件:defense.out   简单对比 时间限制:1 s   内存限制:128 MB 题目描述: 近来A国和B国的矛盾激化,为了预防不测,A国 ...

  7. [haoi2011]防线修建

    动态加点维护凸包. 论STL的熟练运用. #include<cstdio> #include<algorithm> #include<cstring> #inclu ...

  8. bzoj2300 [HAOI2011]防线修建 离线凸包

    这个题可以在线做,splay维护凸包的同时维护区间最值线段树,当删除一个点就找跨过这个点的不在凸包上的点的y最值,然后分下去 由于一次确定一个点,所以复杂度还是nlogn的,只是比较难写 如果一个操作 ...

  9. BZOJ 2300: [HAOI2011]防线修建|set维护凸壳

    因为只支持插入操作,所以需要倒过来做.. 第一次写维护凸壳的东西-不抄题解..自己YY斜率乱搞(都忘了写叉乘)代码又长常数又大 1A一刻赛艇~ 还是找一个靠谱的的模板吧... #include< ...

最新文章

  1. AI竟然可以预测性取向,女装大佬在算法面前不堪一击!
  2. linux下怎么卸载ogg,OGG在Linux上的安装
  3. 使用Xshell连接Ubuntu
  4. android学习笔记17——对话框(PopupWindow)
  5. git-索引-1909
  6. Ajax--同源策略,jsonp跨域传输原理(callback),
  7. Ubuntu 安装Samba(Linux与Windows共享文件)
  8. android wear系统源码,android wear5.1怎么样 android wear5.1更新评测
  9. Bex5开发平台分辨率问题解决方法
  10. VGG16和VGG19
  11. gif如何转html,gif动画怎么转视频格式 gif转swf工具
  12. 图片(img)alt属性标签怎么写
  13. element 如何使用自定义icon图标
  14. Excel如何快速录入甲乙丙丁序列
  15. windows server 2012 DHCP
  16. Android 学习笔记-时间_日期_记时器_倒计时器
  17. 常用英文单词标准缩写
  18. 定义一个函数gcd,功能为求a与b的最大公约数
  19. 如何安装Redis?
  20. 任意十六进制数转换成十进制数----不管你输入多长都能转换

热门文章

  1. java实现对json字符串格式美化
  2. 如何通过7个步骤编写出色的在线用户手册,让天下没有难用的产品
  3. layui 年选择器
  4. 2022 IBM博士生奖学金揭晓:8位华人入选,上交大、电子科大校友在列
  5. 【机器学习与深度学习理论要点】05.监督学习,非监督学习概念及应用场景
  6. 中科院计算机博士学位答辩 顾智宇,中科院论文答辩情况和学位授予决议书.doc...
  7. Git 基础知识 -- 环境配置、搭建Git服务器
  8. PHP跨域处理 图片跨域 接口跨域 后端nginx的cors设置
  9. pmbok第六版变化说明
  10. 解决Vista老版本无法在网页中使用五笔及搜狗拼音