【洛谷】 P2894 [USACO08FEB]Hotel G (线段树)
洛谷 P2894 [USACO08FEB]Hotel G
-
题意:\(n\)个房间,\(m\)个操作,每次有2中操作,操作1为在\([1,n]\)中查询长度为\(x\)的连续空房间,输出最小的最左端的房间id,然后占用这\(x\)个房间,操作2使得\([x,x+y-1]\)这么多房间空出来.
-
题解:连续的区间和问题,经典用线段树来解决,即pushup的时候维护左儿子的区间右端点连续情况和右儿子的区间左端点的连续情况,这样就可以保证每次维护的连续情况。
-
代码:
#include <bits/stdc++.h> using namespace std; const int N=1e6+10; const int mod=1e9+7; #define ll long long #define pb push_back int n,m; struct Node{ int l,r; int tag; int lmx,rmx; int mx; }tr[N<<4]; void push_up(int u){ if(tr[u<<1].mx==tr[u<<1].r-tr[u<<1].l+1) tr[u].lmx=tr[u<<1].mx+tr[u<<1|1].lmx; else tr[u].lmx=tr[u<<1].lmx; if(tr[u<<1|1].mx==tr[u<<1|1].r-tr[u<<1|1].l+1) tr[u].rmx=tr[u<<1|1].mx+tr[u<<1].rmx; else tr[u].rmx=tr[u<<1|1].rmx; tr[u].mx=max({tr[u<<1].mx,tr[u<<1|1].mx,tr[u<<1].rmx+tr[u<<1|1].lmx}); } void push_down(int u){ if(tr[u].tag==1){ tr[u<<1].lmx=tr[u<<1].rmx=tr[u<<1].mx=tr[u<<1].r-tr[u<<1].l+1; tr[u<<1].tag=1; tr[u<<1|1].lmx=tr[u<<1|1].rmx=tr[u<<1|1].mx=tr[u<<1|1].r-tr[u<<1|1].l+1; tr[u<<1|1].tag=1; } if(tr[u].tag==0){ tr[u<<1].lmx=tr[u<<1].rmx=tr[u<<1].mx=0; tr[u<<1].tag=0; tr[u<<1|1].lmx=tr[u<<1|1].rmx=tr[u<<1|1].mx=0; tr[u<<1|1].tag=0; } tr[u].tag=-1; } void build(int u,int l,int r){ if(l==r){ tr[u]={l,r,-1,1,1,1}; return; } tr[u]={l,r,-1,0,0,0}; int mid=(l+r)>>1; build(u<<1,l,mid); build(u<<1|1,mid+1,r); push_up(u); } void update(int u,int L,int R,int f){ if(tr[u].l>=L && tr[u].r<=R){ if(!f){ //填上 tr[u].mx=0; tr[u].lmx=tr[u].rmx=0; tr[u].tag=0; } else{ //清空 tr[u].mx=tr[u].r-tr[u].l+1; tr[u].lmx=tr[u].rmx=tr[u].mx; tr[u].tag=1; } return; } push_down(u); int mid=(tr[u].l+tr[u].r)>>1; if(L<=mid) update(u<<1,L,R,f); if(R>mid) update(u<<1|1,L,R,f); push_up(u); } int query(int u,int L,int R,int x){ if(L==R) return L; push_down(u); int mid=(L+R)>>1; if(tr[u<<1].mx>=x) return query(u<<1,L,mid,x); else if(tr[u<<1].rmx+tr[u<<1|1].lmx>=x) return mid-tr[u<<1].rmx+1; else return query(u<<1|1,mid+1,R,x); } int main(){ scanf("%d %d",&n,&m); build(1,1,n); while(m--){ int op; scanf("%d",&op); if(op==1){ int x; scanf("%d",&x); if(tr[1].mx<x){ puts("0"); continue; } int ans=query(1,1,n,x); printf("%d\n",ans); update(1,ans,ans+x-1,0); } else{ int l,r; scanf("%d %d",&l,&r); update(1,l,l+r-1,1); } } return 0; }
𝓐𝓬𝓱𝓲𝓮𝓿𝓮𝓶𝓮𝓷𝓽 𝓹𝓻𝓸𝓿𝓲𝓭𝓮𝓼 𝓽𝓱𝓮 𝓸𝓷𝓵𝔂 𝓻𝓮𝓪𝓵
𝓹𝓵𝓮𝓪𝓼𝓾𝓻𝓮 𝓲𝓷 𝓵𝓲𝓯𝓮