联考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));
	}
}

原文地址:https://www.cnblogs.com/IzayoiDoyo/p/13429671.html