• [USACO08FEB]Hotel 题解


    正确的题解

    首先我们都知道这题要用线段树做。考虑维护靠左边的answer,靠右边的answer,和整个区间的answer,那么就珂以维护这道题目了。
    这里比较复杂的有下传操作和上传操作。

    上传

    void pushUp(int pos, int l, int r){
        seg[pos].ans = max(seg[pos << 1].rans + seg[pos << 1 | 1].lans, max(seg[pos << 1].ans, seg[pos << 1 | 1].ans));
        int mid = (l + r) >> 1;
        if (seg[pos << 1].ans == mid - l + 1)
            seg[pos].lans = seg[pos << 1 | 1].lans + seg[pos << 1].ans;
        else
            seg[pos].lans = seg[pos << 1].lans;
        if (seg[pos << 1 | 1].ans == r - mid)
            seg[pos].rans = seg[pos << 1].rans + seg[pos << 1 | 1].ans;
        else
            seg[pos].rans = seg[pos << 1 | 1].rans;
    }
    

    下传

    void pushDown(int pos, int l, int r){
        if (!seg[pos].lazy){
            seg[pos << 1].lazy = seg[pos << 1 | 1].lazy = 0;
            int mid = (l + r) >> 1;
            seg[pos << 1].ans = seg[pos << 1].lans = seg[pos << 1].rans = mid - l + 1;
            seg[pos << 1 | 1].ans = seg[pos << 1 | 1].lans = seg[pos << 1 | 1].rans = r - mid;
        }
        else if (seg[pos].lazy == 1){
            seg[pos << 1].lazy = seg[pos << 1 | 1].lazy = 1;
            seg[pos << 1].ans = seg[pos << 1].lans = seg[pos << 1].rans = 0;
            seg[pos << 1 | 1].ans = seg[pos << 1 | 1].lans = seg[pos << 1 | 1].rans = 0;
        }
        seg[pos].lazy = -1;
    }
    
    

    正解代码

    #include <cstdio>
    #include <algorithm>
    
    using namespace std;
    
    int read(){
        int x = 0; int zf = 1; char ch = ' ';
        while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
        if (ch == '-') zf = -1, ch = getchar();
        while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); return x * zf;
    }
    
    struct Node{
        int ans, lans, rans;
        int lazy; 
    } seg[200000];
    
    void pushUp(int pos, int l, int r){
        seg[pos].ans = max(seg[pos << 1].rans + seg[pos << 1 | 1].lans, max(seg[pos << 1].ans, seg[pos << 1 | 1].ans));
        int mid = (l + r) >> 1;
        if (seg[pos << 1].ans == mid - l + 1)
            seg[pos].lans = seg[pos << 1 | 1].lans + seg[pos << 1].ans;
        else
            seg[pos].lans = seg[pos << 1].lans;
        if (seg[pos << 1 | 1].ans == r - mid)
            seg[pos].rans = seg[pos << 1].rans + seg[pos << 1 | 1].ans;
        else
            seg[pos].rans = seg[pos << 1 | 1].rans;
    }
    
    void pushDown(int pos, int l, int r){
        if (!seg[pos].lazy){
            seg[pos << 1].lazy = seg[pos << 1 | 1].lazy = 0;
            int mid = (l + r) >> 1;
            seg[pos << 1].ans = seg[pos << 1].lans = seg[pos << 1].rans = mid - l + 1;
            seg[pos << 1 | 1].ans = seg[pos << 1 | 1].lans = seg[pos << 1 | 1].rans = r - mid;
        }
        else if (seg[pos].lazy == 1){
            seg[pos << 1].lazy = seg[pos << 1 | 1].lazy = 1;
            seg[pos << 1].ans = seg[pos << 1].lans = seg[pos << 1].rans = 0;
            seg[pos << 1 | 1].ans = seg[pos << 1 | 1].lans = seg[pos << 1 | 1].rans = 0;
        }
        seg[pos].lazy = -1;
    }
    
    void build(int pos, int l, int r){
        if (l == r){
            seg[pos].ans = seg[pos].lans = seg[pos].rans = 1;
            seg[pos].lazy = -1;
            return ;
        }
        int mid = (l + r) >> 1;
        build(pos << 1, l, mid), build(pos << 1 | 1, mid + 1, r);
        pushUp(pos, l, r);
    }
    
    void modify(int pos, int l, int r, int x, int y, int val){
        if (x <= l && r <= y){
            if (val) seg[pos].ans = seg[pos].lans = seg[pos].rans = 0;
            else seg[pos].ans = seg[pos].lans = seg[pos].rans = r - l + 1;
            seg[pos].lazy = val;
            return ;
        }
        pushDown(pos, l, r); int mid = (l + r) >> 1;
        if (x <= mid) modify(pos << 1, l, mid, x, y, val);
        if (y > mid) modify(pos << 1 | 1, mid + 1, r, x, y, val);
        pushUp(pos, l, r);
    }
    
    int query(int pos, int l, int r, int k){
        pushDown(pos, l, r); if (l == r) return l;
        int mid = (l + r) >> 1;
        if (seg[pos << 1].ans >= k) return query(pos << 1, l, mid, k);
        if (seg[pos << 1].rans + seg[pos << 1 | 1].lans >= k) return (mid - seg[pos << 1].rans + 1);
        else return query(pos << 1 | 1, mid + 1, r, k);
    }
    
    int main(){
        int n = read(), m = read();
        build(1, 1, n);
        for (int i = 1; i <= m; ++i){
            int op = read(), x, y;
            if (op == 1){
                x = read();
                if(seg[1].ans >= x){
                    int l = query(1, 1, n, x);
                    printf("%d
    ", l);
                    modify(1, 1, n, l, l + x - 1, 1);
                }
                else
                    puts("0");
            }
            else{
                x = read(), y = read();
                modify(1, 1, n, x, x + y - 1, 0);
            }
        }
        return 0;
    }
    

    提供一种新的得高分思路

    这是我发这篇题解的目的,我们看到这熟悉的区间推平操作,很容易就想到了珂朵莉树,也就是我一开始的打法,但是由于数据的原因珂树T了,伤心.jpg。
    我们考虑珂朵莉树的查询,显然我们只需要更改一下查询即可

    int query(int k){
        int l = 1, cnt = 0;
        for (set<Node>::iterator it = st.begin(); it != st.end(); ++it){
            if (it->val == 1){
                l = it->r + 1;
                cnt = 0;
            }
            else{
                cnt += it->r - it->l + 1;
                if (cnt >= k) return l;
            }
        }
        return -1;
    }
    

    我们考虑把连在一起的块的值为零的区间的长度加起来,取第一个满足条件的端点,然后就珂以做出来啦。

    可怜的92分代码

    #include <cstdio>
    #include <vector>
    #include <algorithm>
    #include <set>
    #include <map>
    
    using namespace std;
    
    int read(){
        int x = 0; int zf = 1; char ch = ' ';
        while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
        if (ch == '-') zf = -1, ch = getchar();
        while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); return x * zf;
    }
    
    //build
    struct Node{
        int l, r;
        mutable bool val;
        Node(int a = -1, int b = -1, int c = 0){
            l = a, r = b, val = c;
        }
        bool operator < (const Node &a) const{
            return l < a.l;
        }
    };
    
    set<Node> st;
    
    //modify
    set<Node>::iterator split(int pos){
        set<Node>::iterator it = st.lower_bound(Node(pos));
        if (it != st.end() && it->l == pos) return it;
        --it; Node tmp = *it; st.erase(it);
        st.insert(Node(tmp.l, pos - 1, tmp.val));
        return st.insert(Node(pos, tmp.r, tmp.val)).first; //first return iterator
    }
    
    void assign(int l, int r, bool val){
        set<Node>::iterator itr = split(r + 1), itl = split(l);
        st.erase(itl, itr);
        st.insert((Node){l, r, val});
    }
    
    //query
    int query(int k){
        int l = 1, cnt = 0;
        for (set<Node>::iterator it = st.begin(); it != st.end(); ++it){
            if (it->val == 1){
                l = it->r + 1;
                cnt = 0;
            }
            else{
                cnt += it->r - it->l + 1;
                if (cnt >= k) return l;
            }
        }
        return -1;
    }
    
    int main(){
        int n = read(), m = read(); st.insert((Node){1, n, 0});
        while (m--){
            int op = read();
            if (op == 1){
                int x = read(), pos = query(x);
                if (pos == -1) puts("0");
                else{
                    printf("%d
    ", pos);
                    assign(pos, pos + x - 1, 1);
                }
            }
            else if (op == 2){
                int x = read(), y = read();
                assign(x, x + y - 1, 0);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    Vue自定义组件
    Vuex状态管理总结
    关于状态管理模式
    Vue路由实现页面跳转的两种方式(router-link和JS)
    Vue过渡效果的实现
    Vue中的DOM操作
    SASS 和 LESS 的区别
    Vue计算属性和侦听器
    zabbix 内置变量
    /proc 目录下文件详解
  • 原文地址:https://www.cnblogs.com/linzhengmin/p/11140727.html
Copyright © 2020-2023  润新知