• P2894 [USACO08FEB]酒店Hotel 线段树


    题目大意

    多次操作
    查询并修改区间内长度==len的第一次出现位置
    修改区间,变为空

    思路

    类似于求区间最大子段和(应该是这个吧,反正我没做过) 维护区间rt的

    从l开始向右的最长长度

    从r开始向左的最长长度

    l到r内的最长长度

    反正维护的是个01序列, 随便做

    又是小错误,第一遍就能过非得debug一小时

    这里懒惰标记有两个,开bool为了省 省不了多少的 内存gg了(可以过样例也是神奇,也许是windows吧)

    还有样例好坑啊,我以为是([5,10])(其实是我没认真看)

    代码

    #include <iostream>
    #include <cstdio>
    #define ls rt << 1
    #define rs rt << 1 | 1
    using namespace std;
    const int maxn=5e4+7;
    const int maxm=2e5+7;
    
    int n, m;
    struct node {
        int l, r, size,lk, rk, k,lazy;
        void delet() {
            lk=rk=k=0;
            lazy=1;
        }
        void add() {
            lk=rk=k=size;
            lazy=2;
        }
    }e[maxm];
    
    int max_2(int a, int b, int c) {
        return max(max(a, b), c);
    }
    
    int read() {
        int x = 0, f = 1; char s = getchar();
        for (; s > '9' || s < '0'; s = getchar()) if (s == '-') f = -1;
        for (; s <= '9' && s >= '0'; s = getchar()) x = x * 10 + s - '0';
        return x * f;
    }
    
    void pushup(int rt) {
        e[rt].k = max_2(e[ls].k, e[rs].k, e[ls].rk + e[rs].lk);
        e[rt].lk = (e[ls].lk == e[ls].size) ? e[ls].lk + e[rs].lk : e[ls].lk;
        e[rt].rk = (e[rs].rk == e[rs].size) ? e[ls].rk + e[rs].rk : e[rs].rk;
    }
    
    void pushdown(int rt) {
        if (e[rt].lazy==1) {
            e[ls].delet();
            e[rs].delet();
            e[rt].lazy = 0;
        } else
        if(e[rt].lazy==2) {
            e[ls].add();
            e[rs].add();
            e[rt].lazy = 0;
        }	
    }
    
    void build(int l, int r, int rt) {
        e[rt].l = l, e[rt].r = r, e[rt].size = r - l + 1;
        if (l == r) {
            e[rt].lk = e[rt].rk = e[rt].k = 1;
            return;
        }
        int mid = (l + r) >> 1;
        build(l, mid, ls);
        build(mid + 1, r, rs);
        pushup(rt);
    }
    
    void update(int L, int R,int k ,int rt) {
        if (L <= e[rt].l && e[rt].r <= R) {
            k==1 ? e[rt].delet() :e[rt].add();
            return;
        }
        pushdown(rt);
        int mid = (e[rt].l + e[rt].r) >> 1;
        if(L <= mid) update(L,R,k,ls);
        if(R > mid) update(L,R,k,rs);
        pushup(rt);
    }
    
    int query(int L, int R, int k, int rt) {
        pushdown(rt);
        int ans=0;
        if(e[ls].k >=k ) ans=query(L,R,k,ls);
        else if(e[ls].rk+e[rs].lk >= k) ans = e[ls].r - e[ls].rk + 1;
        else if(e[rs].k >= k)ans = query(L,R,k,rs);
        pushup(rt);
        return ans;
    }
    void yangli_debug()
    {
        printf("debug
    ");
        printf("               %d
    ", e[1].k);
        printf("       %d               %d
    ",e[2].k,e[3].k );
        printf("   %d       %d       %d       %d
    ",e[4].k,e[5].k,e[6].k,e[7].k );
        printf(" %d   %d   %d   %d   %d   %d   %d   %d
    ", e[8].k,e[9].k,e[10].k,e[11].k,e[12].k,e[13].k,e[14].k,e[15].k);
        for(int i=16;i<=31;++i)
            cout<<e[i].k<<" ";
        puts("");
    }
    int main() {
        n = read(), m = read();
        build(1, n, 1);
    
        for (; m--;) {
            int tmp = read();
            if (tmp == 1) {
                int a = read();
                if (e[1].k >= a) {
                    int ans = query(1, n, a, 1);
                    printf("%d
    ", ans);
                    update(ans, ans + a-1, 1, 1);
                } else {
                    puts("0");
                }
            } else {
                int a = read(), b = read();
                update(a, a+b-1, 2,1);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    关于token的理解
    JavaScript 中 call()、apply()、bind() 的用法
    常用JS整理
    js里面for循环的++i与i++
    前端命名规范
    H5混合开发app常用代码
    jquery知识巩固
    水平垂直居中(固定宽不固定宽)
    css3新属性运用
    bug笔记(pc)
  • 原文地址:https://www.cnblogs.com/dsrdsr/p/9753207.html
Copyright © 2020-2023  润新知