[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;
}
原文地址:https://www.cnblogs.com/linzhengmin/p/11140727.html