传送门
这题可以使用线段树做,每个节点维护三个信息:前缀、后缀和中间的最大值。但是,线段树的题怎么能用线段树做呢,所以我写了一个fhq treap的代码(成功把蓝题变成紫题)
平衡树可以维护数列信息。具体做法是将平衡树的节点以下标为关键字组织,即节点在平衡树内的rank即为其在数列里的位置。这样,每个子树都代表一个区间。
为了输出位置,每个节点还要格外记录横跨其的段的左端点相对于其代表的区间的左端点的偏移量(即crossl数组)。在查询的时候,delta记录该区间的左端点的位置。
要注意pushup和pushdown不能乱。
#include <cstdio>
#include <iostream>
using namespace std;
const int maxn = 5e4+5;
int readint(){
int x=0,f=1;char s=getchar();
#define sc (s=getchar())
while(s<'0'||s>'9'){
if(s=='-')
f=-1;
sc;
}
while(s>='0'&&s<='9'){
x=(x<<3)+(x<<1)+(s^48);
sc;
}
#undef sc
return x*f;
}
struct zz{
int l,r,lazy;
int lm,rm,m;
}t[maxn<<2];
void push(int num,int v){
if(v==1)
t[num].lm=t[num].rm=t[num].m=0;
else
t[num].lm=t[num].rm=t[num].m=t[num].r-t[num].l+1;
t[num].lazy=v;
}
void push_up(int num){
t[num].lm=t[num<<1].lm;
t[num].rm=t[num<<1|1].rm;
if(t[num].lm==t[num<<1].r-t[num<<1].l+1)
t[num].lm+=t[num<<1|1].lm;
if(t[num].rm==t[num<<1|1].r-t[num<<1|1].l+1)
t[num].rm+=t[num<<1].rm;
t[num].m=max(max(t[num<<1].m,t[num<<1|1].m),t[num<<1].rm+t[num<<1|1].lm);
}
void push_down(int num){
if(t[num].lazy==-1){
return;
}
push(num<<1,t[num].lazy);
push(num<<1|1,t[num].lazy);
t[num].lazy=-1;
}
void build(int l,int r,int num){
t[num].l=l;
t[num].r=r;
t[num].lm=t[num].rm=t[num].m=r-l+1;
if(l==r)
return ;
int mid=(l+r)>>1;
build(l,mid,num<<1);
build(mid+1,r,num<<1|1);
}
void update(int goal_l,int goal_r,int num,int v){
if(goal_l<=t[num].l&&goal_r>=t[num].r){
push(num,v);
return ;
}
push_down(num);
int mid=(t[num].l+t[num].r)>>1;
if(goal_r<=mid)
update(goal_l,goal_r,num<<1,v);
else if(goal_l>mid)
update(goal_l,goal_r,num<<1|1,v);
else{
update(goal_l,mid,num<<1,v);
update(mid+1,goal_r,num<<1|1,v);
}
push_up(num);
}
int query(int num,int d){
if(t[num].m<d){
return 0;
}
if(t[num].l==t[num].r)
return t[num].l;
push_down(num);
int mid=(t[num].l+t[num].r)>>1;
if(t[num<<1].m>=d)
return query(num<<1,d);
else if(t[num<<1].rm+t[num<<1|1].lm>=d)
return mid-t[num<<1].rm+1;
else if(t[num<<1|1].m>=d)
return query(num<<1|1,d);
}
int main (){
//freopen("hotel.in","r",stdin);
//freopen("hotel.out","w",stdout);
int n=readint(),m=readint();
build(1,n,1);
while(m--){
int t=readint();
if(t==1){
int x=readint();
int ans=query(1,x);
printf("%d\n",ans);
if(ans){
update(ans,ans+x-1,1,1);
}
}
else{
int x=readint(),d=readint();
update(x,x+d-1,1,0);
}
}
return 0;
}