#線段樹#洛谷 4269 [USACO18FEB]Snow Boots G
阿新 • • 發佈:2021-10-19
線段樹
分析
模型轉換一下,能通過當且僅當最長的無法通過段小於 \(d\),(這點應該是此題的精華吧)
那麼按照最大深度從小到大排序,雙指標線上段樹上刪除無法通過段,求最長區間即可
程式碼
#include <cstdio> #include <cctype> #include <algorithm> #define rr register using namespace std; const int N=100011; struct rec{int x,w,rk;}q[N]; int w[N<<2],wl[N<<2],wr[N<<2],a[N],rk[N],ans[N],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 print(int ans){ if (ans>9) print(ans/10); putchar(ans%10+48); } bool cmp1(int x,int y){return a[x]<a[y];} bool cmp2(rec x,rec y){return x.x<y.x;} inline void build(int k,int l,int r){ w[k]=wl[k]=wr[k]=r-l+1; if (l==r) return; rr int mid=(l+r)>>1; build(k<<1,l,mid); build(k<<1|1,mid+1,r); } inline void update(int k,int l,int r,int x){ if (l==r) {w[k]=wl[k]=wr[k]=0; return;} rr int mid=(l+r)>>1; if (x<=mid) update(k<<1,l,mid,x); else update(k<<1|1,mid+1,r,x); w[k]=max(w[k<<1],w[k<<1|1]); w[k]=max(w[k],wr[k<<1]+wl[k<<1|1]); wl[k]=wl[k<<1],wr[k]=wr[k<<1|1]; if (w[k<<1]==mid-l+1) wl[k]+=wl[k<<1|1]; if (w[k<<1|1]==r-mid) wr[k]+=wr[k<<1]; } signed main(){ n=iut(),m=iut(); for (rr int i=1;i<=n;++i) a[i]=iut(),rk[i]=i; for (rr int i=1;i<=m;++i) q[i]=(rec){iut(),iut(),i}; sort(rk+1,rk+1+n,cmp1),sort(q+1,q+1+m,cmp2),build(1,1,n); for (rr int i=1,j=1;i<=m;++i){ for (;j<=n&&a[rk[j]]<=q[i].x;++j) update(1,1,n,rk[j]); if (w[1]<q[i].w) ans[q[i].rk]=1; } for (rr int i=1;i<=m;++i) putchar(ans[i]+48),putchar(10); return 0; }