两个题目都是用同一个模板,询问最长的连续未覆盖的区间 。
lazy代表是否有人,msum代表区间内最大的连续长度,lsum是从左结点往右的连续长度,rsum是从右结点往左的连续长度。
区间合并很恶心啊,各种左左右右左右左右........
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
# define MAX 211111
# define ll(x) x << 1
# define rr(x) x << 1 | 1
using namespace std;
struct node {
int l,r,mid,lazy;
int msum,lsum,rsum;
} tree[MAX*4];
void up(int x) {
int p = tree[x].r - tree[x].l + 1;
tree[x].msum = max(tree[rr(x)].lsum + tree[ll(x)].rsum, max(tree[ll(x)].msum, tree[rr(x)].msum));
tree[x].lsum = tree[ll(x)].lsum;
tree[x].rsum = tree[rr(x)].rsum;
if(tree[x].lsum == p - (p >> 1)) tree[x].lsum += tree[rr(x)].lsum;
if(tree[x].rsum == (p >> 1)) tree[x].rsum += tree[ll(x)].rsum;
}
void down (int x) {
int p = tree[x].r - tree[x].l + 1;
if(tree[x].lazy != -1) {
tree[ll(x)].lazy = tree[rr(x)].lazy = tree[x].lazy;
tree[ll(x)].lsum = tree[ll(x)].rsum = tree[ll(x)].msum = tree[x].lazy ? 0 : p - (p>>1);
tree[rr(x)].lsum = tree[rr(x)].rsum = tree[rr(x)].msum = tree[x].lazy ? 0 : (p>>1);
tree[x].lazy = -1;
}
}
void build(int l,int r,int x) {
tree[x].l = l;
tree[x].r = r;
tree[x].mid = (l+r) >> 1;
tree[x].lazy = -1;
tree[x].lsum = tree[x].rsum = tree[x].msum = r - l + 1;
if(l == r) {
return ;
}
build(l,tree[x].mid,ll(x));
build(tree[x].mid+1,r,rr(x));
}
void update(int l,int r,int v,int x) {
if(l == tree[x].l && r == tree[x].r) {
tree[x].msum = tree[x].lsum = tree[x].rsum = v ? 0: tree[x].r - tree[x].l + 1;
tree[x].lazy = v;
return ;
}
down(x);
if(r <= tree[x].mid ) update(l,r,v,ll(x));
else if(l > tree[x].mid) update(l,r,v,rr(x));
else {
update(l,tree[x].mid,v,ll(x));
update(tree[x].mid + 1,r,v,rr(x));
}
up(x);
}
int query(int v,int x) {
if(tree[x].l == tree[x].r) return tree[x].l;
down(x);
if(tree[ll(x)].msum >= v) return query(v,ll(x));
else if(tree[ll(x)].rsum + tree[rr(x)].lsum >= v) return tree[x].mid - tree[ll(x)].rsum + 1;
else {
return query(v,rr(x));
}
}
int main() {
return 0;
}