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

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

-----------------------------------------------------------------------

#include<cmath>

#include<cstdio>

#include<cctype>

#include<cstring>

#include<cstdlib>

#include<algorithm>

using namespace std;

#define sqr(x) ((x) * (x))

#define Dist(a, b) sqrt(sqr(a.x - b.x) + sqr(a.y - b.y))

#define K(a, b) ((double) (a.y - b.y) / (a.x - b.x))

const int maxn = 100009;

const double eps = 1e-9;

double ans[maxn], res;

int N, Q, q[maxn], n;

bool F[maxn];

inline int read() {

char c = getchar();

for(; !isdigit(c); c = getchar());

int ret = 0;

for(; isdigit(c); c = getchar())

ret = ret * 10 + c - ‘0‘;

return ret;

}

struct P {

int x, y;

P(int _x = 0, int _y = 0) : x(_x), y(_y) {

}

bool operator < (const P &t) const {

return x < t.x || (x == t.x && y < t.y);

}

bool operator == (const P &t) const {

return x == t.x && y == t.y;

}

bool operator != (const P &t) const {

return x != t.x || y != t.y;

}

} p[maxn];

struct Node {

Node *ch[2];

P o;

int r;

} pool[maxn], *pt, *Root, *Null;

void Init_Treap() {

pt = pool;

Null = pt++;

Null->ch[0] = Null->ch[1] = Null;

Root = Null;

}

Node* newNode(P o) {

pt->o = o;

pt->r = rand();

pt->ch[0] = pt->ch[1] = Null;

return pt++;

}

void Rotate(Node*&t, int d) {

Node* o = t->ch[d ^ 1];

t->ch[d ^ 1] = o->ch[d];

o->ch[d] = t;

t = o;

}

void Delete(Node*&t, P o) {

int d = (t->o == o ? -1 : (t->o < o));

if(d == -1) {

if(t->ch[0] != Null && t->ch[1] != Null) {

int _d = (t->ch[0]->r > t->ch[1]->r);

Rotate(t, _d), Delete(t->ch[_d], o);

} else

t = (t->ch[0] != Null ? t->ch[0] : t->ch[1]);

} else

Delete(t->ch[d], o);

}

void Insert(Node*&t, P o) {

if(t == Null) {

t = newNode(o);

} else {

int d = (t->o < o);

Insert(t->ch[d], o);

if(t->ch[d]->r > t->r) Rotate(t, d ^ 1);

}

}

Node* Pred(P o) {

Node* ret;

for(Node* t = Root; t != Null; ) if(t->o < o) {

ret = t, t = t->ch[1];

} else

t = t->ch[0];

return ret;

}

Node* Succ(P o) {

Node* ret;

for(Node* t = Root; t != Null; ) if(o < t->o) {

ret = t, t = t->ch[0];

} else

t = t->ch[1];

return ret;

}

bool chk(P o) {

for(Node* t = Root; t != Null; ) {

if(t->o.x == o.x) return o.y > t->o.y;

t = (t->o < o ? t->ch[1] : t->ch[0]);

}

return true;

}

void Add(P o) {

Node *L = Pred(o), *R = Succ(o), *LL, *RR;

if(R->o.x == o.x) return;

if(L->o.x == o.x) {

LL = Pred(L->o);

res += Dist(LL->o, o) + Dist(R->o, o) - Dist(L->o, R->o) - Dist(LL->o, L->o);

Delete(Root, L->o);

L = Pred(o);

} else if(K(R->o, o) - K(L->o, o) > eps) {

return;

} else

res += Dist(L->o, o) + Dist(R->o, o) - Dist(L->o, R->o);

Insert(Root, o);

if(L->o != P(0, 0)) {

LL = Pred(L->o);

while(L->o != P(0, 0) && K(o, L->o) - K(LL->o, L->o) > eps) {

Delete(Root, L->o);

res += Dist(LL->o, o) - Dist(LL->o, L->o) - Dist(L->o, o);

L = LL, LL = Pred(L->o);

}

}

if(R->o != P(n, 0)) {

RR = Succ(R->o);

while(R->o != P(n, 0) && K(RR->o, R->o) - K(R->o, o) > eps) {

Delete(Root, R->o);

res += Dist(RR->o, o) - Dist(RR->o, R->o) - Dist(R->o, o);

R = RR, RR = Succ(R->o);

}

}

}

void Work() {

for(int i = 0; i < N; i++)

if(!F[i]) Add(p[i]);

for(int i = Q; i--; ) if(~q[i]) {

if(F[q[i]]) Add(p[q[i]]);

F[q[i]] = false;

} else

ans[i] = res;

for(int i = 0; i < Q; i++)

if(!~q[i]) printf("%.2lf\n", ans[i]);

}

void Init() {

n = read();

int x = read(), y = read();

Init_Treap();

Insert(Root, P(0, 0));

Insert(Root, P(n, 0));

Insert(Root, P(x, y));

res = sqrt(x * x + y * y) + sqrt(sqr(x - n) + y * y);

N = read();

for(int i = 0; i < N; i++)

p[i].x = read(), p[i].y =read();

memset(F, 0, sizeof F);

Q = read();

for(int i = 0; i < Q; i++) if((q[i] = read()) != 2) {

F[--(q[i] = read())] = true;

} else

q[i] = -1;

}

int main() {

Init();

Work();

return 0;

}

-----------------------------------------------------------------------

2300: [HAOI2011]防线修建

Time Limit: 10 Sec  Memory Limit: 512 MB
Submit: 623  Solved: 330
[Submit][Status][Discuss]

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点的保护,那么防线变成下图

Input

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

第二行,一个整数m。

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

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

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

Output

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

Sample Input

4 2 1

2

1 2

3 2

5

2

1 1

2

1 2

2

Sample Output

HINT

6.47

5.84

4.47

数据范围:

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

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

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

Source

时间: 2024-11-03 21:29:41

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

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

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

[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国上层询问对于剩下要保护的城市,修建防线的总经费最少

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

听说有一种很高端的东西叫动态凸包维护dp就像学一下,不过介于本人还不会动态凸包就去学了下,还是挺神奇的说,维护上下凸包的写法虽然打得有点多不过也只是维护复制黏贴的事情而已罢了. 先说下动态凸包怎么写吧,搞棵平衡树存上下凸壳然后每次插入一个点就往他左右维护看是否满足凸性否则就弹出,就是这么简单 这道题就是删点然后询问凸壳,那么离线反着做就行了 出题人还是挺良心的直接让你维护上凸壳就行了,还不用管边界条件 用set打了一下,比较慢但还是挺好打的= = 换新blog挺多功能得试试的,现在想搞个像HZW

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).但是这样只能插点不能删点,所以离线处理一下,把删点转化为插点,最后倒着输出. (我比