聯考20200803 T2 感受清風
阿新 • • 發佈:2020-08-03
分析:
我的好像和題解不大一樣
先開一顆線段樹維護貼著邊緣的箱子,每一段區間維護一個\(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)); } }