线段树区间合并模板题
注意查询好时的操作
1. 优先查询左子树
1. 当左子树的lsum >= K 返回l
2. 返回左子树r - rsum + 1
2. 返回右子树
被 1 - N 的更新卡了好久,写篇题解记录
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
const int MAX_N = 50000;
#define LC (index<<1)
#define RC (index<<1|1)
#define LSON (index<<1),(L),(mid)
#define RSON (index<<1|1),(mid+1),(R)
struct node {
int l,r,len;
int lsum,rsum,msum;
int mid()
{
return (this->l + this->r) >> 1;
}
};
node nodes[(MAX_N << 2) + 10];
int N,M;
void build(int index,int L,int R)
{
nodes[index].l = L;
nodes[index].r = R;
nodes[index].len = R -L + 1;
nodes[index].msum = nodes[index].lsum = nodes[index].rsum = nodes[index].len;
if (L == R) return;
int mid = nodes[index].mid();
build(LSON);
build(RSON);
}
void pushup(int index) {
if (nodes[index].l == nodes[index].r) return;;
nodes[index].msum = max(nodes[LC].msum,nodes[RC].msum);
nodes[index].msum = max(nodes[index].msum,nodes[LC].rsum + nodes[RC].lsum);
nodes[index].lsum = nodes[LC].lsum;
if (nodes[LC].lsum == nodes[LC].len) {
nodes[index].lsum += nodes[RC].lsum;
}
nodes[index].rsum = nodes[RC].rsum;
if (nodes[RC].rsum == nodes[RC].len) {
nodes[index].rsum += nodes[LC].rsum;
}
}
void pushdown(int index) {
if (nodes[index].l == nodes[index].r) return;;
if (nodes[index].msum == nodes[index].len) {
nodes[LC].msum = nodes[LC].lsum = nodes[LC].rsum = nodes[LC].len;
nodes[RC].msum = nodes[RC].lsum = nodes[RC].rsum = nodes[RC].len;
}
if (nodes[index].msum == 0) {
nodes[LC].msum = nodes[LC].lsum = nodes[LC].rsum = 0;
nodes[RC].msum = nodes[RC].lsum = nodes[RC].rsum = 0;
}
}
void leave(int index,int L,int R) {
pushdown(index);
if (L <= nodes[index].l && nodes[index].r <= R) {
nodes[index].lsum = nodes[index].rsum = nodes[index].msum = nodes[index].len;
return;
}
int mid = nodes[index].mid();
if (L <= mid) leave(LC,L,R);
if (R > mid) leave(RC,L,R);
pushup(index);
}
void place(int index,int L,int R) {
pushdown(index);
if (L <= nodes[index].l && nodes[index].r <= R) {
nodes[index].msum = nodes[index].lsum = nodes[index].rsum = 0;
pushdown(index);
return;
}
int mid = nodes[index].mid();
if (L <= mid) place(LC,L,R);
if (mid < R) place(RC,L,R);
pushup(index);
}
int query(int index,int K) {
pushdown(index);
if (nodes[index].msum < K) {
return 0;
}
if (nodes[index].l == nodes[index].r) {
int l = nodes[index].l;
int r = l + K - 1;
place(index,l,r);
return nodes[index].l;
}
if (nodes[LC].lsum >= K) {
int l = nodes[index].l;
int r = l + K - 1;
place(index,l,r);
pushup(index);
return nodes[LC].l;
}
int ans;
if (nodes[LC].msum >= K) {
ans = query(LC,K);
pushup(index);
return ans;
}
if (nodes[LC].rsum != 0 && nodes[LC].rsum + nodes[RC].lsum >= K) {
int l = nodes[LC].r - nodes[LC].rsum + 1;
int r = l + K - 1;
place(index,l,r);
pushup(index);
return l;
}
ans = query(RC,K);
pushup(index);
return ans;
}
int main()
{
//freopen("C:\\Users\\klchen\\Desktop\\out.txt","w",stdout);
while (~scanf("%d%d",&N,&M)) {
build(1,1,N);
for (int i = 0;i < M;i++) {
int q,k,l,r;
scanf("%d",&q);
if (q == 1) {
scanf("%d",&k);
printf("%d\n",query(1,k));
} else if (q == 2) {
scanf("%d%d",&l,&k);
r = l + k;
leave(1,l,r - 1);
}
}
}
return 0;
}