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
*/