zoukankan      html  css  js  c++  java
  • POJ 3667 Hotel

    POJ_3667

        第一次接触区间合并的问题,更多区间合并的问题可以参考胡浩的博客http://www.notonlysuccess.com/index.php/segment-tree-complete/

        既然要查询是否存在一个长为d的连续空区间,那么我们至少要记录对于每个区间而言,其中的最长的连续空区间是多大,这个用mc[](max contiguous)表示。同时在查找的过程中,连续空区间有三种形式,在左子树,在右子树,或者横跨两棵子树。当然我们要优先找左子树,最后再找右子树,那么中间的这个横跨的怎么办呢?于是我们可以引入lc[](left contiguous)表示一个区间从左边开始连续最长的区间是多少,rc[](right contiguous)表示一个区间从右边开始连续最长的区间是多少,如果rc[left son]+lc[right son]>=d,那么就说明存在这样一个横跨两棵子树的区间,由于我们知道左子树最右边点的坐标x,那么这个连续空区间的第一个位置自然就是x-rc[left son]+1。

        查找功能实现了之后,剩下的就是染色了,如果是住进去就都染成0,如果是搬出来就都染成1。

        此外,我们在染色之后只要更新父节点mc[]、lc[]、rc[]的状态的,这时对于父节点这个区间,最长的连续区间除了左子树中最长的和右子树中最长的,还要将横跨两棵子树的最长的连续区间也纳入考虑的范围。

    #include<stdio.h>
    #include<string.h>
    #define MAXD 50010
    int N, M, mc[4 * MAXD], lc[4 * MAXD], rc[4 * MAXD], flag[4 * MAXD];
    int getmax(int x, int y)
    {
    return x > y ? x : y;
    }
    void build(int cur, int x, int y)
    {
    int mid = (x + y) / 2, ls = 2 * cur, rs = 2 * cur + 1;
    mc[cur] = lc[cur] = rc[cur] = y - x + 1;
    flag[cur] = -1;
    if(x == y)
    return ;
    build(ls, x, mid);
    build(rs, mid + 1, y);
    }
    void pushdown(int cur, int x, int y)
    {
    int mid = (x + y) / 2, ls = 2 * cur, rs = 2 * cur + 1;
    if(flag[cur] != -1)
    {
    flag[ls] = flag[rs] = flag[cur];
    mc[ls] = lc[ls] = rc[ls] = (flag[cur] ? 0 : mid - x + 1);
    mc[rs] = lc[rs] = rc[rs] = (flag[cur] ? 0 : y - mid);
    flag[cur] = -1;
    }
    }
    void update(int cur, int x, int y)
    {
    int mid = (x + y) / 2, ls = 2 * cur, rs = 2 * cur + 1;
    mc[cur] = getmax(mc[ls], mc[rs]);
    mc[cur] = getmax(mc[cur], rc[ls] + lc[rs]);
    lc[cur] = lc[ls] + (lc[ls] == mid - x + 1 ? lc[rs] : 0);
    rc[cur] = rc[rs] + (rc[rs] == y - mid ? rc[ls] : 0);
    }
    int Search(int cur, int x, int y, int d)
    {
    int mid = (x + y) / 2, ls = 2 * cur, rs = 2 * cur + 1;
    if(x == y)
    return x;
    pushdown(cur, x, y);
    if(mc[ls] >= d)
    return Search(ls, x, mid, d);
    else if(rc[ls] + lc[rs] >= d)
    return mid - rc[ls] + 1;
    else
    return Search(rs, mid + 1, y, d);
    }
    void color(int cur, int x, int y, int s, int t, int c)
    {
    int mid = (x + y) / 2, ls = 2 * cur, rs = 2 * cur + 1;
    if(x >= s && y <= t)
    {
    flag[cur] = c;
    mc[cur] = lc[cur] = rc[cur] = (c ? 0 : y - x + 1);
    return ;
    }
    pushdown(cur, x, y);
    if(mid >= s)
    color(ls, x, mid, s, t, c);
    if(mid + 1 <= t)
    color(rs, mid + 1, y, s, t, c);
    update(cur, x, y);
    }
    void solve()
    {
    int i, j, k, r, d, x;
    for(i = 0; i < M; i ++)
    {
    scanf("%d", &k);
    if(k == 1)
    {
    scanf("%d", &d);
    if(mc[1] < d)
    printf("0\n");
    else
    {
    r = Search(1, 1, N, d);
    printf("%d\n", r);
    color(1, 1, N, r, r + d - 1, 1);
    }
    }
    else
    {
    scanf("%d%d", &x, &d);
    color(1, 1, N, x, x + d - 1, 0);
    }
    }
    }
    int main()
    {
    while(scanf("%d%d", &N, &M) == 2)
    {
    build(1, 1, N);
    solve();
    }
    return 0;
    }


  • 相关阅读:
    Core的学习三:容器的使用实例
    Core的学习二:【四步完成】.Net Core中Log4net的使用,配置,【框架.NET5】
    C#7 的一些新语法
    C#6 的一些新语法
    Core的学习一:Core部署在IIS下
    C# 特性【Attribute】【什么是特性?以及特性的一些修饰】
    C#反射
    泛型 -Generic 【why,原理,与普通方法,object的性能对比如何?泛型类、泛型方法、泛型接口、泛型委托,泛型约束,协变 逆变,泛型缓存】
    springboot通过切面编程实现系统请求操作日志记录
    Linux 【安装配置VM虚拟机】
  • 原文地址:https://www.cnblogs.com/staginner/p/2424331.html
Copyright © 2011-2022 走看看