当前位置: 代码迷 >> 综合 >> luogu2894 [USACO08FEB]Hotel G线段树维护最大连续区间
  详细解决方案

luogu2894 [USACO08FEB]Hotel G线段树维护最大连续区间

热度:11   发布时间:2023-11-24 00:31:57.0

题意:n个旅馆,m次操作,操作1查询长度为x的连续空置房间并入住(取最左区间),没有返回0,操作2退x-y之间的房

线段树维护lmax表示空房间可以向左延伸的最大距离,rmax表示空房间可以向右延伸的最大距离,sum表示空房间个数,lazy表示房间状态是入住或退房

#include <bits/stdc++.h>
using namespace std;
const int maxn = 100005;
struct node
{int lmax,rmax,sum,lazy,l,r,len;
}tree[maxn<<2];
void build(int root, int l, int r) {tree[root].l = l, tree[root].r = r, tree[root].len = r - l + 1;tree[root].lazy = 0; tree[root].sum = tree[root].lmax = tree[root].rmax = tree[root].len;if(l == r)return;int mid = (l + r) >> 1; build(root<<1, l, mid);build(root<<1|1, mid+1, r);
}
void push_up(int root) {if(tree[root<<1].len == tree[root<<1].sum) tree[root].lmax = tree[root<<1|1].lmax + tree[root<<1].len;else tree[root].lmax = tree[root<<1].lmax;if(tree[root<<1|1].len == tree[root<<1|1].sum) tree[root].rmax = tree[root<<1].rmax + tree[root<<1|1].len;else tree[root].rmax = tree[root<<1|1].rmax;tree[root].sum = max(tree[root<<1].sum, max (tree[root<<1|1].sum, tree[root<<1].rmax + tree[root<<1|1].lmax));
}
void push_down(int root) {if(!tree[root].lazy)return;if(tree[root].lazy == 1) {tree[root<<1].sum = tree[root<<1].lmax = tree[root<<1].rmax = 0;tree[root<<1|1].sum = tree[root<<1|1].lmax = tree[root<<1|1].rmax = 0;tree[root<<1].lazy = tree[root<<1|1].lazy = 1;}else {tree[root<<1].sum = tree[root<<1].lmax = tree[root<<1].rmax = tree[root<<1].len;tree[root<<1|1].sum = tree[root<<1|1].lmax = tree[root<<1|1].rmax = tree[root<<1|1].len;tree[root<<1].lazy = tree[root<<1|1].lazy = 2;}tree[root].lazy = 0;
}
void update(int root, int l, int r, int tag) {if(l <= tree[root].l && tree[root].r <= r) {if(tag == 1) tree[root].sum = tree[root].lmax = tree[root].rmax = 0;else tree[root].sum = tree[root].lmax = tree[root].rmax = tree[root].len;tree[root].lazy = tag;return;}push_down(root);int mid = (tree[root].l + tree[root].r) >> 1;if(mid >= l) update(root<<1, l, r, tag);if(r > mid) update(root<<1|1, l, r, tag);push_up(root);
}
int ask(int root, int length) {// cout<<tree[root].l << " " << tree[root].r<<" "<<tree[root<<1].rmax<<" "<<tree[root<<1|1].lmax<<endl;push_down(root);if(tree[root].len == 1)return tree[root].l;int mid = (tree[root].l + tree[root].r) >> 1;if(tree[root<<1].sum >= length) return ask(root<<1,length);if(tree[root<<1].rmax + tree[root<<1|1].lmax >= length) return mid - tree[root<<1].rmax + 1;if(tree[root<<1|1].sum >= length) return ask(root<<1|1, length);return 0; 
}
int main() {std::ios::sync_with_stdio(false);std::cin.tie(nullptr);int n,m;cin>>n>>m;build(1,1,n);while(m--) {int opt;cin>>opt;if(opt == 1) {int x;cin>>x;int left = ask(1,x);cout<<left<<endl;if(left) {update(1,left,left+x-1,1);// for(int i=1;i<=2*n;i++)// 	cout<<tree[i].l <<" "<<tree[i].r<<" "<<tree[i].sum<<endl;}}else {int x,y;cin>>x>>y;update(1,x,x+y-1,2);}}return 0;
}