bzoj2300

http://www.lydsy.com/JudgeOnline/problem.php?id=2300

终于对了。。。

平衡树又写挂了。。。不要忘记清空原先的root和修改root。。。

#include<bits/stdc++.h>
using namespace std;
const int N = 200010;
const double eps = 1e-8;
struct query {
    int x, opt;
} q[N];
struct data {
    double x, y; int cut;
} a[N];
int m, Q, len;
double ans[N];
double ans1, n;
namespace splaytree
{
    int root;
    int child[N][2], fa[N];
    void zig(int x)
    {
        int y = fa[x];
        fa[x] = fa[y]; child[fa[x]][child[fa[x]][1] == y] = x;
        child[y][0] = child[x][1]; fa[child[x][1]] = y;
        fa[y] = x; child[x][1] = y;
    }
    void zag(int x)
    {
        int y = fa[x];
        fa[x] = fa[y]; child[fa[x]][child[fa[x]][1] == y] = x;
        child[y][1] = child[x][0]; fa[child[x][0]] = y;
        fa[y] = x; child[x][0] = y;
    }
    void splay(int x, int t)
    {
        while(fa[x] != t)
        {
            int y = fa[x], z = fa[y];
            if(z == t)
            {
                child[y][0] == x ? zig(x) : zag(x); break;
            }
//            child[y][0] == x ? zig(x) : zag(x);
//            child[z][0] == x ? zig(x) : zag(x);
            else if(y == child[z][0] && x == child[y][0]) { zig(y); zig(x); }
              else if(y == child[z][1] && x == child[y][1]) { zag(y); zag(x); }
               else if(y == child[z][0] && x == child[y][1]) { zag(x); zig(x); }
            else if(y == child[z][1] && x == child[y][0]) { zig(x); zag(x); }
        }
        if(!t) root = x;
    }
    void add(data t, int k)
    {
        if(!root) { root = k; return; }
        int now = root;
        while(1)
        {
            if(!child[now][t.x > a[now].x])
            {
                fa[k] = now; child[now][t.x > a[now].x] = k;
                splay(k, 0); return;
            }
            now = child[now][t.x > a[now].x];
        }
    }
    void del(int x)
    {
        splay(x, 0);
        if(child[x][0] * child[x][1] == 0)
        {
            root = child[x][0] + child[x][1];
            fa[root] = fa[x] = child[x][0] = child[x][1] = 0; return;
        }
        int now = child[x][1];
        while(child[now][0]) now = child[now][0];
        fa[child[x][0]] = now; child[now][0] = child[x][0];
        root = child[x][1]; fa[root] = fa[x] = child[x][0] = child[x][1] = 0;
        splay(now, 0);
    }
    int Pre(int x)
    {
        splay(x, 0);
        x = child[x][0];
        if(!x) return 0;
        while(child[x][1]) x = child[x][1];
        return x;
    }
    int Next(int x)
    {
        splay(x, 0);
        x = child[x][1];
        if(!x) return 0;
        while(child[x][0]) x = child[x][0];
        return x;
    }
    double slope(int x, int y)
    {
        return (a[y].y - a[x].y) / (a[y].x - a[x].x);
    }
    double sqr(double x)
    {
        return x * x;
    }
    double dis(int x, int y)
    {
        if(!x || !y) return 0;
        return sqrt(sqr(a[x].x - a[y].x) + sqr(a[x].y - a[y].y));
    }
    void insert(data t, int x)
    {
        add(t, x);
        int pre = Pre(x), nxt = Next(x);
        ans1 += dis(x, pre) + dis(x, nxt) - dis(nxt, pre);
        if(!pre || !nxt) return;
        splay(pre, x); splay(nxt, x);
        if(slope(pre, x) - slope(x, nxt) <= eps) { ans1 -= dis(x, pre) + dis(x, nxt) - dis(pre, nxt); del(x); return; }
        int ppre = Pre(pre), nnxt = Next(nxt);
        while(ppre && slope(x, pre) - slope(pre, ppre) >= eps)
        {
            ans1 -= dis(pre, x) + dis(pre, ppre) - dis(x, ppre);
            del(pre); pre = ppre; ppre = Pre(pre);
        }
        while(nnxt && slope(x, nxt) - slope(nxt, nnxt) <= eps)
        {
            ans1 -= dis(nxt, x) + dis(nxt, nnxt) - dis(x, nnxt);
            del(nxt); nxt = nnxt; nnxt = Next(nxt);
        }
    }
} using namespace splaytree;
int main()
{
//    freopen("defense1.in", "r", stdin);
//    freopen("defense.out", "w", stdout);
    scanf("%lf%lf%lf%d", &n, &a[2].x, &a[2].y, &m); m += 3;
    a[3].x = n; a[3].y = 0;
    for(int i = 4; i <= m; ++i) scanf("%lf%lf", &a[i].x, &a[i].y);
    scanf("%d", &Q);
    for(int i = 1; i <= Q; ++i)
    {
        scanf("%d", &q[i].opt);
        if(q[i].opt == 1)
        {
            scanf("%d", &q[i].x);
            a[q[i].x + 3].cut = 1;
        }
    }
    len = 0;
    for(int i = 1; i <= m; ++i) if(!a[i].cut) insert(a[i], i);
    for(int i = Q; i; --i)
        if(q[i].opt == 1) insert(a[q[i].x + 3], q[i].x + 3);
        else if(q[i].opt == 2) ans[++len] = ans1;
    for(int i = len; i; --i) printf("%.2f\n", ans[i]);
//    fclose(stdin); fclose(stdout);
    return 0;
}

时间: 2024-10-10 23:45:16

bzoj2300的相关文章

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

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

bzoj2300【HAOI2011】防线修建

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

bzoj-2300 防线修建

题意: 给出一个点集,每次可能删去一个点或查询上凸包的面积: 保证无重点,保证最左面 最右面的点一定在凸包上: n<=100000,m<=200000: 题解: 动态凸包问题,然而这道题的保证简直极为良心: 所以呢,我们就可以用set来水这道题啦: 我还是涨了不少姿势的,比如迭代器居然可以自减: 离线所有的操作之后处理,就是凸包加点了: 每次来一个点,判断一下加不加入,之后左面干点右面干点,插进去就好了: 不过这题细节还是用很多,主要是边界问题吧: 时间复杂度O(set(n))O(nlogn)

BZOJ-2300 [HAOI2011]防线修建

将问题离线倒序处理,问题变成动态加点维护凸包. #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #include <iostream> #include <cctype> #include <set> #define rep(i, l, r) for(int i=l; i&

[BZOJ2300]防线修建

第一次写水平序凸包,感觉跟极角序凸包差不多 凸包的删除看上去不太可做,但我们发现这题没有强制在线,所以我们离线统计答案 离线之后把操作反序,删除就变为插入了 用平衡树维护凸包,每插入一个点,就不停删除它左右两边不满足凸包性质的点 每个点只会被插入删除各一次,不会超时 1 #include<stdio.h> 2 #include<math.h> 3 #include<set> 4 using namespace std; 5 const double eps=1e-8;

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):

有趣的凸壳问题~

PART I  BZOJ 1249 1249: SGU277 HERO 动态凸包 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 406  Solved: 123[Submit][Status] Description 平面上最开始只包含3个点,然后还会依次出现N个点.每新增一个点,请你求出包含这些点的周长最小的多边形的面积(也就是凸包的面积). Input 第一行为6个整数,表示最初的三个点的坐标(x1,y1),(x2,y2),(x3,y3).

[转载]hzwer的bzoj题单

counter: 664BZOJ1601 BZOJ1003 BZOJ1002 BZOJ1192 BZOJ1303 BZOJ1270 BZOJ3039 BZOJ1191 BZOJ1059 BZOJ1202 BZOJ1051 BZOJ1001 BZOJ1588 BZOJ1208 BZOJ1491 BZOJ1084 BZOJ1295 BZOJ3109 BZOJ1085 BZOJ1041 BZOJ1087 BZOJ3038 BZOJ1821 BZOJ1076 BZOJ2321 BZOJ1934 BZOJ

瞎题表

数据结构小练习bzoj3221:[Codechef FEB13] Obserbing the tree树上询问 树剖+主席树(区间修改,加等差数列)bzoj2735:世博会 主席树+切比雪夫距离转曼哈顿距离+我最弱的数学推理bzoj3217:ALOEXT 替罪羊套01Trie(我的码力还是弱得不行,傻逼错误一大堆……)精细的实现果然很重要(对于数据结构里的点(比如……),可以直接提取其维护的区间然后操作的啊)替罪羊的插入重建好像使得重建点的祖先的cover不正确了?然而并没有什么影响?(zyf提