[HNOI/AHOI2018]游戏

题目大意:
  $n(nle10^6)$个房间排成一排,相邻两个房间之间有一扇门。其中一些门上了锁,钥匙在某个给定的房间内。$q(qle10^6)$次询问,每次询问若一开始在$s$房间,能否到达$t$房间。

思路:
  [JOISC2017]細長い屋敷改编题。

 1 #include<cstdio>
 2 #include<cctype>
 3 #include<algorithm>
 4 inline int getint() {
 5     register char ch;
 6     while(!isdigit(ch=getchar()));
 7     register int x=ch^'0';
 8     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
 9     return x; 
10 }
11 const int N=1e6+1;
12 int pos[N],l[N],r[N],right[N];
13 int main() {
14     const int n=getint(),m=getint(),q=getint();
15     for(register int i=0;i<m;i++) {
16         const int x=getint(),y=getint();
17         pos[x]=y;
18     }
19     for(register int i=n;i;i--) {
20         for(l[i]=right[i]=i;right[i]<n&&(!pos[right[i]]||(i<=pos[right[i]]&&pos[right[i]]<=right[i]));) {
21             right[i]=right[right[i]+1];
22         }
23     }
24     for(register int i=1;i<=n;i++) {
25         r[i]=right[i];
26         loop:
27             if(l[i]!=1&&(!pos[l[i]-1]||(l[i]<=pos[l[i]-1]&&pos[l[i]-1]<=r[i]))) {
28                 const int j=l[i]-1;
29                 l[i]=std::min(l[i],l[j]);
30                 r[i]=std::max(r[i],r[j]);
31                 goto loop;
32             }
33             if(r[i]!=n&&(!pos[r[i]]||(l[i]<=pos[r[i]]&&pos[r[i]]<=r[i]))) {
34                 const int j=r[i]+1;
35                 r[i]=std::max(r[i],right[j]);
36                 goto loop;
37             }
38     }
39     for(register int i=0;i<q;i++) {
40         const int s=getint(),t=getint();
41         puts(l[s]<=t&&t<=r[s]?"YES":"NO");
42     }
43     return 0;
44 }
原文地址:https://www.cnblogs.com/skylee03/p/8857416.html