#線段樹,二分#洛谷 2824 [HEOI2016/TJOI2016]排序
阿新 • • 發佈:2020-08-09
分析
這排序就很難實現,考慮定一個基準,小於該基準的視為0,否則視為1,
那排序可以看作將0和1分開,這就很好用線段樹實現了
如果該位置是0,說明這個基準太高,顯然可以用二分答案(基準),那麼時間複雜度就是\(O((n+m)log^2n)\)
程式碼
#include <cstdio> #include <cctype> #define rr register using namespace std; const int N=100011; int lazy[N<<2],w[N<<2],a[N],n,L[N],R[N],m; inline signed iut(){ rr int ans=0; rr char c=getchar(); while (!isdigit(c)) c=getchar(); while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar(); return ans; } inline void build(int k,int l,int r,int now){ if (l==r) {lazy[k]=-1,w[k]=a[l]>=now; return;} rr int mid=(l+r)>>1; build(k<<1,l,mid,now),build(k<<1|1,mid+1,r,now); w[k]=w[k<<1]+w[k<<1|1],lazy[k]=-1; } inline void pdown(int k,int l,int r){ rr int mid=(l+r)>>1; if (lazy[k]) w[k<<1]=mid-l+1,w[k<<1|1]=r-mid; else w[k<<1]=w[k<<1|1]=0; lazy[k<<1]=lazy[k<<1|1]=lazy[k],lazy[k]=-1; } inline void update(int k,int l,int r,int x,int y,int z){ if (l==x&&r==y) {w[k]=z*(r-l+1),lazy[k]=z; return;} if (~lazy[k]) pdown(k,l,r); rr int mid=(l+r)>>1; if (y<=mid) update(k<<1,l,mid,x,y,z); else if (x>mid) update(k<<1|1,mid+1,r,x,y,z); else update(k<<1,l,mid,x,mid,z),update(k<<1|1,mid+1,r,mid+1,y,z); w[k]=w[k<<1]+w[k<<1|1]; } inline signed query(int k,int l,int r,int x,int y){ if (l==x&&r==y) return w[k]; if (~lazy[k]) pdown(k,l,r); rr int mid=(l+r)>>1; if (y<=mid) return query(k<<1,l,mid,x,y); else if (x>mid) return query(k<<1|1,mid+1,r,x,y); else return query(k<<1,l,mid,x,mid)+query(k<<1|1,mid+1,r,mid+1,y); } inline bool check(int now,int pos){ build(1,1,n,now); for (rr int i=1,f;i<=m;++i){ if (L[i]<0) f=-1,L[i]=-L[i]; else f=1; rr int cnt=query(1,1,n,L[i],R[i]),h=R[i]-L[i]+1; if (~f){ if (cnt<h) update(1,1,n,L[i],R[i]-cnt,0); if (cnt) update(1,1,n,R[i]-cnt+1,R[i],1); } else{ if (cnt<h) update(1,1,n,L[i]+cnt,R[i],0); if (cnt) update(1,1,n,L[i],L[i]+cnt-1,1); } L[i]*=f; } return query(1,1,n,pos,pos); } signed main(){ n=iut(); m=iut(); for (rr int i=1;i<=n;++i) a[i]=iut(); for (rr int i=1;i<=m;++i){ rr int z=iut()?-1:1; L[i]=iut()*z,R[i]=iut(); } rr int l=1,r=n,pos=iut(); while (l<r){ rr int mid=(l+r+1)>>1; if (check(mid,pos)) l=mid; else r=mid-1; } return !printf("%d",l); }