1. 程式人生 > >[HNOI2018]遊戲

[HNOI2018]遊戲

getc 編號 type 不想 shuff getchar 因此 fine clu

Description:

一次小G和小H在玩尋寶遊戲,有n個房間排成一列,編號為\(1,2,...,n\),相鄰的房間之間都有一道門。其中一部分們上鎖(因此需要有對應的鑰匙才能開門),其余的門都能直接打開。現在小G告訴了小H每把鎖的鑰匙在哪個房間裏(每把鎖鎖有且只有一把鑰匙與之對應),並作出p次指示:第i次讓小H從第\(S_i\)個房間出發到\(T_i\)個房間裏。但是小G有時會故意在指令中放入死路,而小H也不想浪費多余的體力去嘗試,於是想事先調查清楚每次的指令是否會存在一條通路。

Hint:

\(n,m,q \le 10^6\)

Solution:

每次直接在一個點暴力向兩邊拓展,但這樣會被卡,隨機化就行了

(然而不隨機化,就是倒著跑還快一點,數據666)

#include <map>
#include <set>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define ls p<<1 
#define rs p<<1|1
using namespace std;
typedef long long ll;
const int mxn=2e6+5;
int n,m,q,cnt,hd[mxn];
int a[mxn],b[mxn],L[mxn],R[mxn];

inline int read() {
    char c=getchar(); int x=0,f=1;
    while(c>'9'||c<'0') {if(c=='-') f=-1;c=getchar();}
    while(c<='9'&&c>='0') {x=(x<<3)+(x<<1)+(c&15);c=getchar();}
    return x*f;
}
inline void chkmax(int &x,int y) {if(x<y) x=y;}
inline void chkmin(int &x,int y) {if(x>y) x=y;}

struct ed {
    int to,nxt;
}t[mxn<<1];

inline void add(int u,int v) {
    t[++cnt]=(ed) {v,hd[u]}; hd[u]=cnt;
}

void expand(int x) {
    int l=x,r=x;
    while(1) {
        int flag=0;
        if(l>1&&((l<=a[l-1]&&a[l-1]<=r)||!a[l-1])) 
            flag=1,--l,l=min(l,L[l]),r=max(r,R[l]);
        if(r<n&&((l<=a[r]&&a[r]<=r)||!a[r])) 
            flag=1,++r,l=min(l,L[r]),r=max(r,R[r]);
        if(!flag) break;    
    }
    L[x]=l,R[x]=r;
}

int main()
{
    n=read(); m=read(); q=read(); int x,y;
    for(int i=1;i<=m;++i) {
        x=read(); y=read();
        a[x]=y;
    }
    for(int i=1;i<=n;++i) L[i]=n+1,R[i]=0,b[i]=i;
    random_shuffle(b+1,b+n+1);
    for(int i=1;i<=n;++i) expand(b[i]);
    while(q--) {
        x=read(); y=read();
        if(L[x]<=y&&y<=R[x]) puts("YES");
        else puts("NO");
    }
    return 0;
}

[HNOI2018]遊戲