1. 程式人生 > >[HNOI/AHOI2018]遊戲

[HNOI/AHOI2018]遊戲

讓我 str etc 如果 || main hnoi inline http

題目描述

https://lydsy.com/JudgeOnline/upload/201804/%E6%B9%96%E5%8D%97%E4%BA%8C%E8%AF%95%E8%AF%95%E9%A2%98.pdf

題解

這道題其實是讓我們對於每個位置,求出它的一個合法區間。

先考慮如果所有的限制都滿足y<=x的限制,說明如果我們如果從一個點出發,就不用來回跑腿了,直接一路向右走就好了。

那麽這時對於每個點,它能擴展到的最左的點就是他向左遇到的第一個門,至於右端點,我們可以倒著掃描一個序列,維護一個棧,如果棧頂在當前是可達的,那麽我們就把它彈掉,因為這個點在任何時候度不會成為端點了。

如何解釋?要麽這個點在將來也可以被通過,要麽存在比它更靠前的一個點變成右端點。

然後這樣是O(n)的。

如果我們這個限制,我們不能直接卡出左端點,可以考慮邊界條件,先卡出一個滿足沒有y<=x的左端點,這是裏面所有的限制都是y>x的,那麽不可達的情況就是y大於當前的右端點,所以我們要找到的就是最靠右的滿足前面那個條件的點。

這個用線段樹維護,結合前面的棧可以做到O(nlogn)。

代碼

#include<iostream>
#include<cstdio>
#define N 1000002
using namespace std;
int n,m,q,tr[N<<2],key[N],st[N],lim[N],top,l[N],r[N];
inline 
int rd(){ int x=0;char c=getchar();bool f=0; while(!isdigit(c)){if(c==-)f=1;c=getchar();} while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();} return f?-x:x; } int work(int cnt,int l,int r,int x){ if(tr[cnt]<=x)return 0; if(l==r)return l; int mid=(l+r)>>1
; if(tr[cnt<<1|1]>x)return work(cnt<<1|1,mid+1,r,x); else return work(cnt<<1,l,mid,x); } int query(int cnt,int l,int r,int L,int R,int x){ if(l>=L&&r<=R)return work(cnt,l,r,x); int mid=(l+r)>>1,ans=0; if(mid<R)ans=query(cnt<<1|1,mid+1,r,L,R,x); if(ans)return ans; if(mid>=L)ans=query(cnt<<1,l,mid,L,R,x); return ans; } void build(int cnt,int l,int r){ if(l==r){tr[cnt]=key[l];return;} int mid=(l+r)>>1; build(cnt<<1,l,mid);build(cnt<<1|1,mid+1,r); tr[cnt]=max(tr[cnt<<1],tr[cnt<<1|1]); } inline int solve(int l,int r,int x){ if(l>r)return l; int pos=query(1,1,n,l,r,x); if(!pos)return l;else return pos+1; } int main(){ n=rd();m=rd();q=rd();int x,y; for(int i=1;i<=m;++i){ x=rd();y=rd(); key[x]=y; } build(1,1,n); lim[1]=1; for(int i=2;i<=n;++i)lim[i]=(key[i-1]&&key[i-1]<=i-1)?i:lim[i-1]; key[n]=n+1; for(int i=n;i>=1;--i){ l[i]=r[i]=i; l[i]=solve(lim[i],i-1,r[i]); st[++top]=i; while(top&&((key[st[top]]>=l[i]&&key[st[top]]<=r[i])||(!key[st[top]]))){ --top; r[i]=st[top]; l[i]=solve(lim[i],i-1,r[i]); } } while(q--){ x=rd();y=rd(); if(l[x]<=y&&y<=r[x])puts("YES"); else puts("NO"); } return 0; }

[HNOI/AHOI2018]遊戲