#include <bits/stdc++.h>
#define rep(ii,a,b) for (int ii=(a);ii<=(b);ii++)
#define rek(ii,a,b) for (int ii=(a);ii>=(b);ii--)
using namespace std;
const int maxn=100010;
int n,m;
int len;
int fa[maxn],c[maxn][2],siz[maxn],lx[maxn],rx[maxn],maxs[maxn],sta[maxn];
int root;
void updata(int x){
if (x==0) return;
siz[x]=siz[c[x][0]]+siz[c[x][1]]+1;
maxs[x]=rx[x]-lx[x]+1;
if (c[x][0]) maxs[x]=max(maxs[x],maxs[c[x][0]]);
if (c[x][1]) maxs[x]=max(maxs[x],maxs[c[x][1]]);
}
void link(int x,int y,int der){
if (x!=0) c[x][der]=y;
if (y!=0) fa[y]=x;
updata(x);
}
void cut(int x,int y,int der){
updata(x);
if (x!=0) c[x][der]=0;
if (y!=0) fa[y]=0;
updata(x);
}
void rorate(int x){
if (fa[x]==0) return ;
int t=fa[x],t1=fa[fa[x]];
int p=(c[t][1]==x);
int p1=(c[fa[t]][1]==t);
link(t1,x,p1);
link(t,c[x][!p],p);
link(x,t,!p);
updata(t);
}
void splay(int x,int y){
while (fa[x]!=y){
if (fa[fa[x]]!=y){
if ((c[fa[x]][0]==x)^(c[fa[fa[x]]][0]==fa[x])){
rorate(x);
}else{
rorate(fa[x]);
}
}
rorate(x);
}
updata(x);
if (y==0) root=x; else updata(y);
}
int getrank(int x,int k){
int i=x;
int j=k;
while (true){
if (j==siz[c[i][0]]+1) return i;
if (siz[c[i][0]]+1<j) {
j-=(siz[c[i][0]]+1);
i=c[i][1];
} else{
i=c[i][0];
}
}
}
void del(int now){
splay(now,0);
int i=c[now][0];
while (c[i][1]) i=c[i][1];
int j=c[now][1];
while (c[j][0]) j=c[j][0];
splay(i,0);
splay(j,i);
c[j][0]=0;
updata(j);
updata(i);
}
int getnext(int now){
splay(now,0);
int i=c[now][1];
while (c[i][0]) i=c[i][0];
return i;
}
int getlast(int now){
splay(now,0);
int i=c[now][0];
while (c[i][1]) i=c[i][1];
return i;
}
int solve(int x){
int i=root;
if (maxs[i]<x) return -1;
while (i){
if (maxs[c[i][0]]>=x && c[i][0]!=0) i=c[i][0];else {
if (rx[i]-lx[i]+1>=x && rx[i]<=n && lx[i]>=0)
{
int ans=lx[i];
splay(i,0);
lx[i]+=x;
updata(i);
if (lx[i]>rx[i]) del(i);
return ans;
}
i=c[i][1];
}
}
}
bool pd_lr(int l,int r,int ll,int rr){
if (l>ll) {swap(l,ll);swap(r,rr);}
if (r==ll-1) return true;
if (r<ll) return false;
if (l>rr) return false;
return true;
}
void cover(int l,int r){
int i=root,j,ans=0;
while (i){
if (rx[i]>=l)
if ((ans==0)||(rx[ans]>rx[i])) ans=i;
if (rx[i]>=l) i=c[i][0];else i=c[i][1];
}
int tlast=getlast(ans);
if (lx[ans]>r+1 && rx[tlast]!=l-1) {
len++;
splay(ans,0);
int j=c[root][0];
while (c[j][1]) j=c[j][1];
splay(j,root);
lx[len]=l;rx[len]=r;
updata(len);
link(j,len,1);
updata(root);
return ;
}
int tt=0,ll=l,rr=r;
i=ans;
if (pd_lr(ll,rr,lx[tlast],rx[tlast])) {i=tlast;tlast=getlast(tlast);}
while (pd_lr(ll,rr,lx[i],rx[i])){
if (lx[i]<ll) ll=lx[i];
if (rx[i]>rr) rr=rx[i];
tt++;
sta[tt]=i;
i=getnext(i);
}
rep(i,1,tt) del(sta[i]);
splay(tlast,0);
i=c[tlast][1];
while (c[i][0]) i=c[i][0];
splay(i,root);
len++;
lx[len]=ll;rx[len]=rr;
maxs[len]=rr-ll+1;
siz[len]=1;
link(i,len,0);
updata(root);
}
int main(){
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
scanf("%d%d",&n,&m);
len=3;
root=1;
lx[1]=0;rx[1]=n-1;
lx[2]=-1;rx[2]=-2;
lx[3]=n+4;rx[3]=n+3;
c[root][0]=2;
c[root][1]=3;
fa[2]=1;fa[3]=1;
rek(i,3,1) updata(i);
rep(i,1,m)
{
int c,x,y;
scanf("%d",&c);
if (c==1) {
scanf("%d",&x);
printf("%d\n",solve(x));
}else
{
scanf("%d%d",&x,&y);
int l=x;
int r=min(x+y-1,n);
cover(l,r);
}
}
return 0;
}
题意不说了。
很显然,这题我们可以用splay做,每个节点维护一段连续的未被占用的区间,以及所在该子树最长的区间。。。这个非常好维护。。比较蛋疼的是2操作,要把所有相关的区间提取出来求并。。然后再插入新节点。。。就是模拟而已。当然也可以用动态开节点的线段树。。不过本人抖m写了个splay
代码: