bzoj5288: [Hnoi2018] Game [Topological Sort]

portal

Problem solving ideas:

Every point can be reached is an interval, consider how to find this interval.
Violent expansion is definitely O ( n 2 ) Yes, to see if there is any nature.

Consider a door, if the key is on the left, the one on the right will never get to the left. But once the left can go to the right, it can go to all the ranges that the right can go, so we connect an edge from the left to the right, and vice versa.

Then we process in topological order. Each time it is judged whether the current interval can go to both sides, if so, continue to expand, and then expand the scope of this interval (merge the expanded interval and jump directly to its edge). Since each interval is merged at most 2 times (once left and once right) the complexity is O ( n )

#include<bits/stdc++.h>
using namespace std;
int getint()
{
    int i=0,f=1;char c;
    for(c=getchar();(c!='-')&&(c<'0'||c>'9');c=getchar());
    if(c=='-')c=getchar(),f=-1;
    for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';
    return i*f;
}
const int N=1000005;
int n,m,Q,p[N],l[N],r[N],id[N];
int tot,first[N],nxt[N],to[N],du[N];
queue<int>q;
void add(int x,int y)
{
    nxt[++tot]=first[x],first[x]=tot,to[tot]=y,du[y]++;
}
void extend(int i)
{
    while(1)
    {
        int bz1=1,bz2=1;
        if(l[i]==1)bz1=0;
        if(r[i]==n)bz2=0;
        if(bz1)
        {
            if((!p[l[i]-1])||(p[l[i]-1]>=l[i]&&p[l[i]-1]<=r[i]))l[i]=l[id[l[i]-1]];
            else bz1=0;
        }
        if(bz2)
        {
            if((!p[r[i]])||(p[r[i]]>=l[i]&&p[r[i]]<=r[i]))r[i]=r[id[r[i]+1]];
            else bz2=0;
        }
        if(!bz1&&!bz2)break;
    }
}
void topsort()
{
    for(int i=1;i<=n;i++)if(id[i]==i&&!du[i])q.push(i);
    while(!q.empty())
    {
        int u=q.front();q.pop();
        extend(u);
        for(int e=first[u];e;e=nxt[e])
            if(!(--du[to[e]]))q.push(to[e]);
    }
}
int main()
{
    //freopen("game.in","r",stdin);
    //freopen("game.out","w",stdout);
    int x,y;
    n=getint(),m=getint(),Q=getint();
    for(int i=1;i<=n;i++)id[i]=l[i]=r[i]=i;
    while(m--)x=getint(),p[x]=getint();
    for(int i=1;i<=n;i++)
    {
        if(!p[i])id[i+1]=id[i];
        else p[i]<=i?add(id[i+1],id[i]):add(id[i],id[i+1]);
    }
    for(int i=1;i<=n;i++)l[id[i]]=min(l[id[i]],l[i]),r[id[i]]=max(r[id[i]],r[i]);
    topsort();
    for(int i=1;i<=n;i++)l[i]=l[id[i]],r[i]=r[id[i]];
    while(Q--)
    {
        x=getint(),y=getint();
        y>=l[x]&&y<=r[x]?puts("YES"):puts("NO");
    }
    //for(int i=1;i<=n;i++)cout<<i<<":"<<l[i]<<' '<<r[i]<<'\n';
    return 0;
}


Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326129803&siteId=291194637