题目:
题目链接:[LUOGU USACO08FEB 酒店Hotel ]
题解:
这个题,就是XOR的艺术和Glass Carving的结合,就是求长度为x的最小房间号的连续0,这样的话就是和Glass一样进行求线段树中的区间连续最大,再像XOR的艺术一样进行修改。
代码:
#include<bits/stdc++.h>
#define lk (k<<1)
#define rk (k<<1|1)
using namespace std;
inline int read()
{
int s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch<='9'&&ch>='0')s=s*10+ch-'0',ch=getchar();
return s*w;
}
const int sea=50100;
int n,m;
struct hit{int l,r,lm,rm,s,len,lazy;}tr[sea*4];
void build(int k,int l,int r)
{
tr[k].l=l,tr[k].r=r;
tr[k].lm=tr[k].rm=tr[k].s=tr[k].len=r-l+1;
if(l==r) return; int mid=(l+r)/2;
build(lk,l,mid); build(rk,mid+1,r);
}
void up(int k)
{
if(tr[lk].s==tr[lk].len) tr[k].lm=tr[rk].lm+tr[lk].len;else tr[k].lm=tr[lk].lm;
if(tr[rk].s==tr[rk].len)
tr[k].rm=tr[lk].rm+tr[rk].len;else tr[k].rm=tr[rk].rm;
tr[k].s=max(max(tr[lk].s,tr[rk].s),tr[rk].lm+tr[lk].rm);
}
void down(int k)
{
int l=tr[k].l,r=tr[k].r;
if(l==r) return ;
if(tr[k].lazy==1)
{
tr[lk].lm=tr[lk].rm=tr[lk].s=tr[lk].len;
tr[rk].lm=tr[rk].rm=tr[rk].s=tr[rk].len;
tr[lk].lazy=tr[rk].lazy=1;
}
else if(tr[k].lazy==2)
{
tr[lk].lm=tr[lk].rm=tr[lk].s=0;
tr[rk].lm=tr[rk].rm=tr[rk].s=0;
tr[lk].lazy=tr[rk].lazy=2;
}
tr[k].lazy=0;
}
void alter(int k,int x,int y,int ff)
{
down(k);
int l=tr[k].l,r=tr[k].r;
if(l==x&&r==y)
{
if(ff==1) tr[k].lm=tr[k].rm=tr[k].s=tr[k].len;
else tr[k].lm=tr[k].rm=tr[k].s=0;
tr[k].lazy=ff; return ;
}
int mid=(l+r)/2;
if(mid>=y) alter(lk,x,y,ff);
else if(mid<x) alter(rk,x,y,ff);
else alter(lk,x,mid,ff),alter(rk,mid+1,y,ff);
up(k);
}
int ask(int k,int x)
{
down(k);
int l=tr[k].l,r=tr[k].r,mid=(l+r)/2;
if(l==r) return l;
if(tr[lk].s>=x) return ask(lk,x);
if(tr[lk].rm+tr[rk].lm>=x) return mid-tr[lk].rm+1;
return ask(rk,x);
}
int main()
{
n=read(); m=read();
build(1,1,n);
for(int i=1;i<=m;i++)
{
int f,x,y;
f=read();
if(f==1)
{
x=read(); if(tr[1].s<x) puts("0");
else{int p=ask(1,x); printf("%d\n",p);alter(1,p,p+x-1,2);}
}
else x=read(),y=read(),alter(1,x,y+x-1,1);
}
return 0;
}