luogu P7476 「C.E.L.U-02」苦涩

https://www.luogu.com.cn/problem/P7476

考虑树套树,每个节点维护一个大根堆

然后如果要删掉为堆顶,如果被包含在删除的区间内,那么直接删掉即可

否则把这个值下放到儿子区间,再继续修改

代码实现不难

code:


#include<bits/stdc++.h>
#define N 200050
#define ls (rt << 1)
#define rs (rt << 1 | 1)
using namespace std;
int mx[N << 3];
priority_queue<int> tg[N << 3];
void update(int rt) {
    mx[rt] = max(mx[ls], mx[rs]);
    if(tg[rt].size()) mx[rt] = max(mx[rt], tg[rt].top());
}
void padd(int rt, int o) {
    tg[rt].push(o), mx[rt] = max(mx[rt], o);
}
void pushdown(int rt) {
    int x = tg[rt].top(); tg[rt].pop();
    padd(ls, x), padd(rs, x);
}
void add(int rt, int l, int r, int L, int R, int o) {// printf("  %d %d %d %d %d\n", rt, l, r, L, R, o);
    if(L <= l && r <= R) {
        padd(rt, o);
        return ;
    }
    int mid = (l + r) >> 1;
    if(L <= mid) add(ls, l, mid, L, R, o);
    if(R > mid) add(rs, mid + 1, r, L, R, o);
    update(rt);
}
int query(int rt, int l, int r, int L, int R) {
    if(L <= l && r <= R) return mx[rt];
    int mid = (l + r) >> 1, ret = -1;
    if(tg[rt].size()) ret = tg[rt].top();
    if(L <= mid) ret = max(ret, query(ls, l, mid, L, R));
    if(R > mid) ret = max(ret, query(rs, mid + 1, r, L, R));
    return ret;
}
void del(int rt, int l, int r, int L, int R, int o) {//printf("%d %d %d %d %d %d   %d\n", rt, l, r, L, R, o, mx[rt]);
    if(mx[rt] < o) return ;
    if(tg[rt].size() && tg[rt].top() == o) {// printf("wdnmd");
        if(L <= l && r <= R) {
            tg[rt].pop();
            update(rt);
            return ;
        }
        pushdown(rt);
    }
//    if(r - l <= 0) {
//        printf("***%d %d %d %d %d %d   %d\n", rt, l, r, L, R, o, mx[rt]);
//        exit(0);
//    }
    int mid = (l + r) >> 1;
    if(L <= mid) del(ls, l, mid, L, R, o);
    if(R > mid) del(rs, mid + 1, r, L, R, o);
    update(rt);
}
int n, m;
int main() {
 //   freopen("a.in","r",stdin);
   // freopen("a.out","w",stdout);
    memset(mx, -1, sizeof mx);
    scanf("%d%d", &n, &m);
 //   m = 6;
    while(m --) {
        int o, l, r, k;
        scanf("%d", &o);
        if(o == 1) {
            scanf("%d%d%d", &l, &r, &k);
            add(1, 1, n, l, r, k);
        }
        if(o == 2) {
            scanf("%d%d", &l, &r);
            int o = query(1, 1, n, l, r);
          //  printf("*%d*", o);
            if(o != -1) del(1, 1, n, l, r, o);
        }
        if(o == 3) {
            scanf("%d%d", &l, &r);
            printf("%d\n", query(1, 1, n, l, r));
        }
        //for(int i = 1; i <= 2 * n; i ++) printf("%d ", mx[i]); printf("\n");
    }
    return 0;
}
/*
 
 6 6
 1 1 6 2
 1 2 3 2
 2 2 3
 2 3 4
 2 2 4
 3 1 6
 */
posted @ 2021-10-12 21:06  lahlah  阅读(37)  评论(0编辑  收藏  举报