1. 程式人生 > 實用技巧 >聯考20200803 T2 感受清風

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