【题解】arc165_d Substring Comparison

arc165_d Substring Comparison

简要题意

给定整数 \(n,m\),以及 \(m\) 个四元组 \((a_i,b_i,c_i,d_i)\)

判断是否存在一个长度为 \(n\) 的正整数序列 \(x\),满足 \(\forall i\in [1,m]\)\(x_{a_i}\sim x_{b_i}\) 组成的序列的字典序严格小于 \(x_{c_i}\sim x_{d_i}\) 组成的序列。

\(n,m\le 2\times 10^3\)

题解

知识点:图论,强连通分量。

启发:

  • 处理多元互相制约的问题考虑建出限制图。

\(n,m\le 2\times 10^3\),说明做法大概在 \(O(n^2)\) 左右。

初始时,建出一个图,将所有 \(a_i\)\(c_i\) 连一条有向边,表示 \(x_{a_i}<x_{c_i}\)

如果当前图中不存在大小 \(\ge 2\) 的强连通分量,那说明是满足条件的,直接输出 Yes,判断这个东西可以用 tarjan 算法。

否则说明存在环,为了解决这个矛盾,只好令该强连通分量里的点代表的 \(x_i\) 都相等,随即找到对应的 \(a_i\)\(c_i\),既然这一位必须得相等了,那就让 \(a_i+1\)\(c_i+1\) 不相等,于是令 \(a_i\leftarrow a_i+1,c_i\leftarrow c_i+1\),然后再重新建图判断。

需要注意的是,如果某次 \(a_i,c_i\) 自增 \(1\) 后使得 \(c_i>d_i\),说明 \(b_i-a_i+1\ge d_i-c_i+1\),即前者区间长度大于等于后者,且他们在后者那段有效前缀得满足完全相等,此时不可能使得前者字典序严格小于后者,故此时输出 No

综上来看,本题不仅可以以两个区间为载体作出限制,更能直接钦定两个子序列作出限制,但显然前者更具有迷惑性。

最坏情况下时间复杂度为 \(O(n(n+m))\),跑了 \(n\)tarjan

#include<bits/stdc++.h>
using namespace std;

#define rep(i,l,r) for(int i=(l);i<=(r);++i)
#define per(i,l,r) for(int i=(r);i>=(l);--i)
#define pr pair<int,int>
#define fi first
#define se second
#define pb push_back
#define all(x) (x).begin(),(x).end()
#define sz(x) (x).size()
#define bg(x) (x).begin()
#define ed(x) (x).end()

#define N 2025
// #define int long long

int n,m,a[N],b[N],c[N],d[N],cnt;
int st[N],tp,fa[N],dfn[N],low[N];
bitset<N>in;
vector<int>e[N];
bool ex;

inline int ask(int k){
    if(fa[k]==k){
        return k;
    }
    return fa[k]=ask(fa[k]);
}

inline bool mg(int x,int y){
    int fx=ask(x),fy=ask(y);

    if(fx==fy){
        return 0;
    }

    fa[fx]=fy;

    return 1;
}

inline void clr(){
    tp=cnt=0;

    rep(i,1,n){
        e[i].clear();
        dfn[i]=low[i]=0;
        in[i]=0;
    }
}

inline void tarjan(int k){
    low[k]=dfn[k]=++cnt;
    st[++tp]=k;
    in[k]=1;
    
    for(int x:e[k]){
        if(!dfn[x]){
            tarjan(x);
            low[k]=min(low[k],low[x]);
        }
        else if(in[x]){
            low[k]=min(low[k],dfn[x]);
        }
    }

    if(low[k]!=dfn[k]){
        return;
    }

    if(st[tp]!=k){
        ex=1;
    }

    while(st[tp]!=k){
        in[st[tp]]=0;
        mg(k,st[tp]);

        tp--;
    }

    in[k]=0;
    tp--;
}

signed main(){
    // freopen(".in","r",stdin);
    // freopen(".out","w",stdout);
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);

    cin>>n>>m;

    rep(i,1,m){
        cin>>a[i]>>b[i]>>c[i]>>d[i];
    }

    rep(i,1,n){
        fa[i]=i;
    }

    rep(i,1,n){
        clr();

        rep(j,1,m){
            while(a[j]<=b[j]&&c[j]<=d[j]&&ask(a[j])==ask(c[j])){
                a[j]++;
                c[j]++;
            }

            if(c[j]>d[j]){
                cout<<"No";
                return 0;
            }

            if(a[j]<=b[j]){
                e[ask(a[j])].pb(ask(c[j]));
            }
        }

        ex=0;

        rep(j,1,n){
            if(!dfn[j]){
                tarjan(j);
            }
        }

        if(!ex){
            break;
        }
    }

    cout<<"Yes";

    return 0;
}
posted @ 2025-07-19 00:17  Lucyna_Kushinada  阅读(5)  评论(0)    收藏  举报