[BZOJ2300][HAOI2011][动态凸包]防线修建
来源:互联网 发布:人工智能 技术论坛 编辑:程序博客网 时间:2024/05/18 01:38
[Problem Description]
近来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)和首都这三个城市是一定需要保护的。
上图中,A,B,C,D,E点为A国城市,且目前都要保护,那么修建的防线就会是A-B-C-D,花费也就是线段AB的长度+线段BC的长度+线段CD的长度。
如果,这个时候撤销B点的保护,那么防线变成下图
[Algorithm & Data Structure]动态凸包
[Analysis]
明显的动态凸包(其实暴力凸包也可以过)。删点比较不好搞,所以倒着算,先把所有删掉的点去掉,然后一个个往里面加。动态凸包写Splay比较蛋疼……
[Code]
/************************************************************** Problem: 2300 User: gaotianyu1350 Language: C++ Result: Accepted Time:620 ms Memory:7640 kb****************************************************************/ #include <cstdio>#include <cstring>#include <cmath>#include <cstdlib>#include <iostream>using namespace std; const int MAXN = 100100;const int MAXQ = 200100; class splay_node{public: splay_node *ch[2], *pre; int x, y, cnt; splay_node(); bool operator < (const splay_node b) const { return (x == b.x && y < b.y) || x < b.x; } bool operator == (const splay_node b) const { return (x == b.x && y == b.y); } int Which() { return pre->ch[0] == this ? 0 : 1; } void Set(splay_node *child, int wh) { ch[wh] = child, child->pre = this; } } splay[MAXN]; int tot = 0;splay_node *root; splay_node::splay_node(){ ch[0] = ch[1] = pre = splay; x = 0; y = 0; cnt = 1;} inline void Rotate(splay_node *now){ splay_node *oldfather = now->pre; splay_node *grand = now->pre->pre; int wh = now->Which(); oldfather->Set(now->ch[wh ^ 1], wh); now->Set(oldfather, wh ^ 1); now->pre = grand; if (grand != splay) grand->ch[grand->ch[0] == oldfather ? 0 : 1] = now;} inline void Splay(splay_node *now, splay_node *tar){ for (; now->pre != tar; Rotate(now)) if (now->pre->pre != tar) now->Which() == now->pre->Which() ? Rotate(now->pre) : Rotate(now); if (tar == splay) root = now;} inline splay_node *Find(int x, int y){ splay_node tar; tar.x = x, tar.y = y; splay_node *now = root; while (now != splay) { if (*now == tar) return now; if (tar < *now) now = now->ch[0]; else now = now->ch[1]; } return now;} inline splay_node *GetPre(splay_node *now){ Splay(now, splay); for (now = now->ch[0]; now->ch[1] != splay; now = now->ch[1]); return now;} inline splay_node *GetNext(splay_node *now){ Splay(now, splay); for (now = now->ch[1]; now->ch[0] != splay; now = now->ch[0]); return now;} inline splay_node *NewNode(int x, int y){ tot++; splay[tot].x = x, splay[tot].y = y; return splay + tot;} inline splay_node *Add(int x, int y){ splay_node tar; tar.x = x, tar.y = y; splay_node *now = root; splay_node *last = splay; if (root == splay) { root = NewNode(x, y); return root; } while (now != splay) { last = now; if (*now == tar) { now->cnt++; return now; } if (tar < *now) now = now->ch[0]; else now = now->ch[1]; } now = NewNode(x, y); if (tar < *last) last->Set(now, 0); else last->Set(now, 1); Splay(now, splay); return now;} inline void Delete(splay_node *now = splay, int x = 0, int y = 0){ if (now == splay) now = Find(x, y); if (now->cnt > 1) { now->cnt--; return; } Splay(now, splay); if (now->ch[0] == splay && now->ch[1] == splay) { root = splay; return; } if (now->ch[0] == splay || now->ch[1] == splay) { root = now->ch[0] == splay ? now->ch[1] : now->ch[0]; root->pre = splay; return; } splay_node *_pre = GetPre(root); Splay(_pre, root); _pre->Set(root->ch[1], 1); root = _pre; root->pre = splay;} int n, x, y, m;int query;int xx[MAXN], yy[MAXN];bool check[MAXN] = { 0 }; struct QueryData{ int k, x; double ans;} qd[MAXQ]; double nowans; inline double dis(int x1, int y1, int x2, int y2){ return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));} inline double dis(splay_node *a, splay_node *b){ return dis(a->x, a->y, b->x, b->y);} inline int cross(splay_node *a, splay_node *b, splay_node *c){ return (b->x - a->x) * (c->y - b->y) - (c->x - b->x) * (b->y - a->y);} inline bool isstart(splay_node *now){ return (now->x == 0 && now->y == 0);} inline bool isend(splay_node *now){ return (now->x == n && now->y == 0);} inline void AddACity(int x, int y){ splay_node *now = Add(x, y); splay_node *_pre = GetPre(now); splay_node *_next = GetNext(now); if (cross(_pre, now, _next) >= 0) { Delete(now); return; } nowans -= dis(_pre, _next); if (!isstart(_pre)) for (splay_node *_prepre = GetPre(_pre); cross(_prepre, _pre, now) >= 0;) { nowans -= dis(_pre, _prepre); Delete(_pre); _pre = _prepre; if (isstart(_pre)) break; _prepre = GetPre(_pre); } if (!isend(_next)) for (splay_node *_nextnext = GetNext(_next); cross(now, _next, _nextnext) >= 0;) { nowans -= dis(_next, _nextnext); Delete(_next); _next = _nextnext; if (isend(_next)) break; _nextnext = GetNext(_next); } nowans += dis(now, _pre) + dis(now, _next);} int main(){ //freopen("input.txt", "r", stdin); scanf("%d%d%d", &n, &x, &y); root = splay; Add(0, 0); Add(n, 0); Add(x, y); nowans = dis(0, 0, x, y) + dis(x, y, n, 0); scanf("%d", &m); for (int i = 1; i <= m; i++) scanf("%d%d", &xx[i], &yy[i]); scanf("%d", &query); for (int i = 1; i <= query; i++) { scanf("%d", &qd[i].k); if (qd[i].k == 1) { scanf("%d", &qd[i].x); check[qd[i].x] = true; } } for (int i = 1; i <= m; i++) if (!check[i]) AddACity(xx[i], yy[i]); for (int i = query; i >= 1; i--) if (qd[i].k == 1) AddACity(xx[qd[i].x], yy[qd[i].x]); else qd[i].ans = nowans; for (int i = 1; i <= query; i++) if (qd[i].k == 2) printf("%.2f\n", qd[i].ans);}
0 0
- [BZOJ2300][HAOI2011][动态凸包]防线修建
- 【bzoj2300】[HAOI2011]防线修建 凸包+set
- 【HAOI2011】【BZOJ2300】防线修建
- bzoj2300【HAOI2011】防线修建
- BZOJ2300: [HAOI2011]防线修建
- 【HAOI2011】bzoj2300 防线修建
- BZOJ2300: [HAOI2011]防线修建
- bzoj2300: [HAOI2011]防线修建 计算几何 凸包
- 【bzoj2300】【HAOI2011】【防线修建】【离线+凸包+set】
- [BZOJ2300][HAOI2011]防线修建(凸包+splay)
- 【bzoj2300】[HAOI2011]防线修建 set维护凸壳
- [bzoj2300][HAOI2011]防线修建(splay)
- BZOJ 2300 [HAOI2011]防线修建 Splay维护动态凸包
- [平衡树动态维护凸包] BZOJ 2300 [HAOI2011]防线修建
- bzoj 2300: [HAOI2011]防线修建(splay动态维护凸包)
- BZOJ 2300 HAOI2011 防线修建 平衡树维护凸包
- 2300: [HAOI2011]防线修建 set维护凸包
- bzoj 2300 [HAOI2011]防线修建 splay维护凸包
- HTML实训课程笔记_03
- 【SSH】登录方式(1)用户名/密码:取远程公钥+用户名/密码 (2)公钥:取数据+本地私钥
- c
- 大学同学聚会
- android如何屏蔽掉home键
- [BZOJ2300][HAOI2011][动态凸包]防线修建
- 为什么要中断线程呢?
- C#TimerCallback事例
- 数据压缩之贪心算法-赫夫曼编码
- 对于C11中的正则表达式的使用
- 工作记录
- 使用Eclipse构建Maven的SpringMVC项目
- 拓扑排序
- scala初步