一开始想复杂了,记录了6个值,代码量相当的大而且update比较麻烦,后来query的时候发现其中有两个值没用,有一个值可以减掉,果断删了重写,虽然wrong了1次,不过还算顺利,A了后看大神的代码,果然够简洁,小改了一下。总体来说,记录左连续,右连续,全局连续就ok了。
ACcode:
#include<stdio.h>
#include<iostream>
using namespace std;
const int size=55555;
struct Node
{
int lc,rc,mc;
int lazy,sum;
} tre[size<<2];
int Max(int a1,int a2)
{
return a1>a2?a1:a2;
}
int Min(int a1,int a2)
{
return a1<a2?a1:a2;
}
void pushup(int rt)
{
int r1=rt<<1,r2=r1|1;
if (tre[r1].lc==tre[r1].sum) tre[rt].lc=tre[r1].lc+tre[r2].lc;
else tre[rt].lc=tre[r1].lc;
if (tre[r2].rc==tre[r2].sum) tre[rt].rc=tre[r1].rc+tre[r2].rc;
else tre[rt].rc=tre[r2].rc;
tre[rt].mc=Max(tre[r1].rc+tre[r2].lc,Max(tre[r1].mc,tre[r2].mc));
}
void build(int rt,int l,int r)
{
tre[rt].lazy=-1;
tre[rt].sum=r-l+1;
if (l==r)
{
tre[rt].lc=tre[rt].rc=tre[rt].mc=1;
return ;
}
int m=(l+r)>>1;
build(rt<<1,l,m);
build(rt<<1|1,m+1,r);
pushup(rt);
}
void pushdown(int rt,int l,int r)
{
if (tre[rt].lazy>=0)
{
int m=(l+r)>>1;
int r1=rt<<1,r2=r1|1,v=tre[rt].lazy;
tre[r1].mc=tre[r1].lc=tre[r1].rc=(m-l+1)*v;
tre[r2].mc=tre[r2].lc=tre[r2].rc=(r-m)*v;
tre[r1].lazy=tre[r2].lazy=tre[rt].lazy;
tre[rt].lazy=-1;
}
}
void update(int rt,int l,int r,int L,int R,int v)
{
if (L<=l&&r<=R)
{
tre[rt].mc=tre[rt].lc=tre[rt].rc=(r-l+1)*v;
tre[rt].lazy=v;
return ;
}
if (l==r) return ;
pushdown(rt,l,r);
int m=(l+r)>>1;
if (L<=m) update(rt<<1,l,m,L,R,v);
if (R>m) update(rt<<1|1,m+1,r,L,R,v);
pushup(rt);
}
int query(int rt,int l,int r,int num)
{
if (l==r) return r;
pushdown(rt,l,r);
int m=(l+r)>>1,pos;
int r1=rt<<1,r2=r1|1;
if (tre[r1].mc>=num) pos=query(r1,l,m,num);
else if ((tre[r1].rc+tre[r2].lc)>=num)
pos=m-tre[r1].rc+1;
else pos=query(r2,m+1,r,num);
return pos;
}
int main()
{
int n,q,op,d,x;
while (~scanf("%d %d",&n,&q))
{
build(1,1,n);
while (q--)
{
scanf("%d",&op);
if (op==1)
{
scanf("%d",&x);
if (tre[1].mc<x) d=0;
else
{
d=query(1,1,n,x);
update(1,1,n,d,x+d-1,0);
}
printf("%d\n",d);
}
else
{
scanf("%d %d",&x,&d);
update(1,1,n,x,x+d-1,1);
}
}
}
return 0;
}