联考20200803 T2 感受清风
分析:
我的好像和题解不大一样
先开一颗线段树维护贴着边缘的箱子,每一段区间维护一个\(mn\)表示能走过这段区间的最大列
left和right实际上是一个镜像翻转,打个标记就好了
对于加入和删除的箱子,暴力用一个二维数据结构维护,发现我们只关心列上区间的关系,就用空间比较小的主席树了
当要进行left或者right操作的时候,把主席树上加的点加入线段树,把主席树清零就可以了
查询的时候两个标记同时在线段树和主席树上查找,注意合并信息,类似线段树二分地找就好了
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define maxn 1000005
using namespace std;
inline int getint()
{
int num=0,flag=1;char c;
while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
while(c>='0'&&c<='9')num=num*10+c-48,c=getchar();
return num*flag;
}
int n,m;
int a[maxn],mn[maxn<<2];
int Rev,Mx;
int rt[maxn],tot;
int lc[maxn*21],rc[maxn*21],val[maxn*21];
struct op{
int op,x,y;
}Q[maxn];
int cur;
char s[maxn];
inline void build(int i,int l,int r)
{
if(l==r){mn[i]=a[l];return;}
int mid=(l+r)>>1;
build(i<<1,l,mid),build(i<<1|1,mid+1,r);
mn[i]=min(mn[i<<1],mn[i<<1|1]);
}
inline void update(int i,int l,int r,int p,int x)
{
if(l==r){mn[i]+=x;return;}
int mid=(l+r)>>1;
if(p<=mid)update(i<<1,l,mid,p,x);
else update(i<<1|1,mid+1,r,p,x);
mn[i]=min(mn[i<<1],mn[i<<1|1]);
}
inline bool check(int now,int i)
{return now?val[now]:(mn[i]>=Mx);}
inline void insert(int &now,int i,int l,int r,int p,int x)
{
if(!now)now=++tot;
if(l==r){val[now]=x;return;}
int mid=(l+r)>>1;
if(p<=mid)insert(lc[now],i<<1,l,mid,p,x);
else insert(rc[now],i<<1|1,mid+1,r,p,x);
val[now]=check(lc[now],i<<1)&check(rc[now],i<<1|1);
}
inline int getu(int now,int i,int l,int r,int p)
{
if(r<=p&&check(now,i))return r-l+1;
if(l==r)return check(now,i);
int mid=(l+r)>>1;
if(p<=mid)return getu(lc[now],i<<1,l,mid,p);
int tmp=getu(rc[now],i<<1|1,mid+1,r,p);
if(tmp==p-mid)return getu(lc[now],i<<1,l,mid,mid)+tmp;
return tmp;
}
inline int getd(int now,int i,int l,int r,int p)
{
if(p<=l&&check(now,i))return r-l+1;
if(l==r)return check(now,i);
int mid=(l+r)>>1;
if(p>mid)return getd(rc[now],i<<1|1,mid+1,r,p);
int tmp=getd(lc[now],i<<1,l,mid,p);
if(tmp==mid-p+1)return getd(rc[now],i<<1|1,mid+1,r,mid+1)+tmp;
return tmp;
}
int main()
{
n=getint(),m=getint();
for(int i=1;i<=n;i++)a[i]=getint();
build(1,1,n);
int q=getint();
while(q--)
{
scanf("%s",s);
if(s[0]=='l'||s[0]=='r')
{
Rev=(s[0]=='r');
for(int i=1;i<=cur;i++)
{
update(1,1,n,Q[i].x,Q[i].op);
rt[Q[i].y]=0;
}
cur=0;continue;
}
int x=getint(),y=getint();
Mx=Rev?m-y+1:y;
if(s[0]=='a')
{
Q[++cur]=(op){1,x,y};
insert(rt[y],1,1,n,x,1);
continue;
}
if(s[0]=='d')
{
Q[++cur]=(op){-1,x,y};
insert(rt[y],1,1,n,x,0);
continue;
}
if(s[1]=='u')printf("%d\n",getu(rt[y],1,1,n,x));
if(s[1]=='d')printf("%d\n",getd(rt[y],1,1,n,x));
}
}