题目描述

给你(0,0)、(n,0)、(x,y)和另外m个点,除(0,0)(n,0)外每个点横坐标都大于0小于n,纵坐标都大于0。

输入

第一行,三个整数n,x,y分别表示河边城市和首都是(0,0),(n,0),(x,y)。
第二行,一个整数m。
接下来m行,每行两个整数a,b表示A国的一个非首都非河边城市的坐标为(a,b)。
再接下来一个整数q,表示修改和询问总数。
接下来q行每行要么形如1 i,要么形如2,分别表示撤销第i个城市的保护和询问。

输出

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

样例输入

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

样例输出

6.47
5.84
4.47


题解

离线+STL-set维护凸包

很容易想到离线,然后转变为加点,维护凸壳周长——经典的动态凸包问题。

把所有凸包上的点按横坐标维护平衡树,插入一个点时,首先看它是否在凸包内。具体方法:找出其前驱后继的点,判断是否上凸。容易验证这样时正确的。

然后考虑加入这个点,需要弹掉什么样的点:左边:找该点的前驱以及前驱的前驱,判断是否上凸,不上凸则弹掉前驱,否则停止。右边同理。

由于一个点只被删除一次,因此时间复杂度时 $O(n\log n)$ 的。

判断上凸可以使用叉积来判断。

由于本题不需要在凸包上二分,因此平衡树只需要维护点坐标,使用STL-set即可。

具体还是看代码吧。

#include <set>
#include <cmath>
#include <cstdio>
#define N 100010
using namespace std;
struct data
{
int x , y;
data() {}
data(int a , int b) {x = a , y = b;}
bool operator<(const data &a)const {return x == a.x ? y < a.y : x < a.x;}
data operator-(const data &a)const {return data(x - a.x , y - a.y);}
int operator*(const data &a)const {return x * a.y - y * a.x;}
inline double calc() {return sqrt(x * x + y * y);}
}a[N];
set<data> s;
int del[N] , opt[N << 1] , v[N << 1];
double now , ans[N << 1];
inline void modify(data p)
{
data a , b;
set<data>::iterator it = s.lower_bound(p);
b = *it , a = *--it;
if((p - a) * (b - p) >= 0) return;
now -= (a - b).calc();
while(it != s.begin())
{
a = *it , b = *--it;
if((p - a) * (b - a) >= 0) now -= (a - b).calc() , s.erase(a);
else break;
}
it = s.lower_bound(p);
while(it != --s.end())
{
a = *it , b = *++it;
if((p - a) * (b - a) <= 0) now -= (a - b).calc() , s.erase(a);
else break;
}
it = s.lower_bound(p) , b = *it , a = *--it;
now += (p - a).calc() + (p - b).calc() , s.insert(p);
}
int main()
{
int k , x , y , n , m , i;
scanf("%d%d%d%d" , &k , &x , &y , &n);
s.insert(data(0 , 0)) , s.insert(data(k , 0)) , s.insert(data(x , y)) , now = data(x , y).calc() + data(x - k , y).calc();
for(i = 1 ; i <= n ; i ++ ) scanf("%d%d" , &a[i].x , &a[i].y);
scanf("%d" , &m);
for(i = 1 ; i <= m ; i ++ )
{
scanf("%d" , &opt[i]);
if(opt[i] == 1) scanf("%d" , &v[i]) , del[v[i]] = 1;
}
for(i = 1 ; i <= n ; i ++ )
if(!del[i])
modify(a[i]);
for(i = m ; i ; i -- )
{
if(opt[i] == 1) modify(a[v[i]]);
else ans[i] = now;
}
for(i = 1 ; i <= m ; i ++ )
if(opt[i] == 2)
printf("%.2lf\n" , ans[i]);
return 0;
}

【bzoj2300】[HAOI2011]防线修建 离线+STL-set维护凸包的更多相关文章

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

    http://www.lydsy.com/JudgeOnline/problem.php?id=2300 维护动态凸包,人懒用的set 用叉积判断,不要用斜率 #include<set> ...

  2. 2019.02.21 bzoj2300: [HAOI2011]防线修建(set+凸包)

    传送门 题意:动态维护凸包周长. 思路: 见这篇求面积的吧反正都是一个套路. 代码: #include<bits/stdc++.h> #define int long long #defi ...

  3. BZOJ2300[HAOI2011]防线修建——非旋转treap+凸包(平衡树动态维护凸包)

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

  4. BZOJ2300: [HAOI2011]防线修建

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2300 (我只是在发以前写过的题.. 因为题目没说强制在线,所以离线乱搞就可以了.先把点删掉然后 ...

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

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

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

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

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

    离线然后倒着做就变成了支持加点的动态凸包...用平衡树维护上凸壳...时间复杂度O(NlogN) --------------------------------------------------- ...

  8. [luogu P2521] [HAOI2011]防线修建

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

  9. P2521 [HAOI2011]防线修建

    题目链接:P2521 [HAOI2011]防线修建 题意:给定点集 每次有两种操作: 1. 删除一个点 (除开(0, 0), (n, 0), 与指定首都(x, y)) 2. 询问上凸包长度 至于为什么 ...

随机推荐

  1. # 20155337 2017-2018-1 《信息安全系统设计基础》第二周课堂实践+myod

    20155337 2017-2018-1 <信息安全系统设计基础>第二周课堂实践+myod 因为在课上已经提交了四个实验,还欠缺最后一个实验,反省一下自己还是操作不熟练,平时在课下应该多多 ...

  2. Redis可视化客户端管理Web UI工具收集

    https://github.com/uglide/RedisDesktopManager(推荐,全平台支持的桌面UI工具) Web方案: https://github.com/ErikDubbelb ...

  3. 监听Entity Framework生成的Sql语句

               Entity Framework为我们提供了很大的方便,但有时候,我们想看看EF生成的Sql语句到底是怎样的,一种方式是我们可以启用Sql Server Profer工具.今天介 ...

  4. vue-cli的安装使用

    通过 npm install vue 安装vue 后: 1.打开cmd 输入 npm install --global vue-cli 全局安装vue-cli脚手架 输入 vue -V 返回vue-c ...

  5. scrapy (一)

    scrapy框架 scrapy 是一个爬虫框架,能够高效率,高层次的爬取页面的数据并进行处理. 在scrapy的英文文档中,有这样的一个流程图 scrapy 框架主要分为五大部分,spider, en ...

  6. 415. Valid Palindrome【LintCode java】

    Description Given a string, determine if it is a palindrome, considering only alphanumeric character ...

  7. Elasticsearch.Net 异常:[match] query doesn't support multiple fields, found [field] and [query]

    用Elasticsearch.Net检索数据,报异常: )); ElasticLowLevelClient client = new ElasticLowLevelClient(settings); ...

  8. 剑指 Offer——和为 S 的两个数字

    1. 题目 2. 解答 由于数组是已经排好序的,我们可以定义两个指针,第一个指针指向第一个元素,第二个指针指向最后一个元素,然后求出这两个元素的和,与目标和进行比较.若小于目标和,第一个指针向前移动: ...

  9. 遗传算法中几种不同选择算子及Python实现

    前言 本文对遗传算法中的几种选择策略进行了总结, 其中包括: Proportionate Roulette Wheel Selection Linear Ranking Selection Expon ...

  10. spark RDD、DataFrame、DataSet之间的相互转化

    这三个数据集看似经常用,但是真正归纳总结的时候,很容易说不出来 三个之间的关系与区别参考我的另一篇blog  http://www.cnblogs.com/xjh713/p/7309507.html ...