結果

問題 No.3188 K-th Lexmin
ユーザー fumofumofuni
提出日時 2025-06-21 18:36:53
言語 C++17
(gcc 13.3.0 + boost 1.87.0)
結果
WA  
実行時間 -
コード長 6,125 bytes
コンパイル時間 2,314 ms
コンパイル使用メモリ 213,944 KB
実行使用メモリ 7,840 KB
最終ジャッジ日時 2025-06-21 18:37:04
合計ジャッジ時間 9,331 ms
ジャッジサーバーID
(参考情報)
judge2 / judge3
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample WA * 1
other TLE * 1 -- * 46
権限があれば一括ダウンロードができます

ソースコード

diff #

#include<bits/stdc++.h>
using namespace std;
#define rep(i,n) for(ll i=0;i<n;i++)
#define repl(i,l,r) for(ll i=(l);i<(r);i++)
#define per(i,n) for(ll i=(n)-1;i>=0;i--)
#define perl(i,r,l) for(ll i=r-1;i>=l;i--)
#define all(x) (x).begin(),(x).end()
#define CST(x) cout<<fixed<<setprecision(x)
#define vtpl(x,y,z) vector<tuple<x,y,z>>
#define rev(x) reverse(x);
using ll=long long;
using vl=vector<ll>;
using vvl=vector<vector<ll>>;
using pl=pair<ll,ll>;
using vpl=vector<pl>;
using vvpl=vector<vpl>;
const ll MOD=1000000007;
const ll MOD9=998244353;
const int inf=1e9+10;
const ll INF=4e18;
const ll dy[9]={1,0,-1,0,1,1,-1,-1,0};
const ll dx[9]={0,1,0,-1,1,-1,1,-1,0};
template<class T> inline bool chmin(T& a, T b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}
template<class T> inline bool chmax(T& a, T b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}


class SuffixArray{
    using vi=vector<int>;
    vi S; int N;
    vi sa_is(const vi &str,const int k){
        const int n=str.size();
        vector<bool> isS(n),isLMS(n);
        vi LMSs;
        isS[n-1]=true;
        for(int i=n-2;i>=0;i--){
            isS[i]=str[i]<str[i+1]||(str[i]==str[i+1]&&isS[i+1]);
        }
        rep(i,n){
            if(isS[i]&(i==0||!isS[i-1])){
                isLMS[i]=true;LMSs.push_back(i);
            }
        }
        vi pseudo_sa=induced_sort(str,LMSs,isS,k);
        vi orderedLMSs(LMSs.size());
        int index=0;
        for(int x:pseudo_sa){
            if(isLMS[x])orderedLMSs[index++]=x;
        }
        pseudo_sa[orderedLMSs[0]]=0;
        int rank=0;
        if(orderedLMSs.size()>1)pseudo_sa[orderedLMSs[1]]=++rank;
        repl(i,1,orderedLMSs.size()-1){
            bool isdiff=false;
            rep(j,n){
                int p=orderedLMSs[i]+j;
                int q=orderedLMSs[i+1]+j;
                if(str[p]!=str[q]||isLMS[p]!=isLMS[q]){
                    isdiff=true;break;
                }
                if(j>0&&isLMS[p])break;
            }
            pseudo_sa[orderedLMSs[i+1]]=isdiff? ++rank:rank;
        }
        vi newstr(LMSs.size());
        index=0;
        rep(i,n){
            if(isLMS[i])newstr[index++]=pseudo_sa[i];
        }
        vi LMS_sa;
        if(rank+1==LMSs.size())LMS_sa=orderedLMSs;
        else {
            LMS_sa=sa_is(newstr,rank+1);
            for(auto& x:LMS_sa)x=LMSs[x];
        }
        return induced_sort(str,LMS_sa,isS,k);
    }

    vi induced_sort(const vi& str,const vi& LMSs,const vector<bool>& isS,const int k){
        int n=str.size();
        vi buckets(n);
        vi chars(k+1);
        for(auto c:str)chars[c+1]++;
        rep(i,k)chars[i+1]+=chars[i];
        vi count(k);
        for(int i=LMSs.size()-1;i>=0;i--){
            int c=str[LMSs[i]];
            buckets[chars[c+1]-1-count[c]++]=LMSs[i];
        }
        count=vi(k);
        rep(i,n){
            if(buckets[i]==0||isS[buckets[i]-1])continue;
            int c=str[buckets[i]-1];
            buckets[chars[c]+count[c]++]=buckets[i]-1;
        }
        count=vi(k);
        for(int i=n-1;i>=0;i--){
            if(buckets[i]==0||!isS[buckets[i]-1])continue;
            int c=str[buckets[i]-1];
            buckets[chars[c+1]-1-count[c]++]=buckets[i]-1;
        }
        return buckets;
    }
    public:
    vi sa,lcp;
    SuffixArray(vector<int> s):S(s),N(s.size()){
        //S+="$";
        vi str(N+1);
        rep(i,N) str[i]=S[i];
        str[N]=0;
        sa=sa_is(str,200010);
        sa.erase(sa.begin());
    }
    /*bool search(string t){
        int l=0,r=N;
        while(r-l>1){
            int mid=(l+r)/2;
            if(S.substr(sa[mid],t.size())<=t)l=mid;
            else r=mid;
        }
        return S.substr(sa[l],t.size())==t;
    }*/
    void construct_lcp(){//lcp[i]:S.substr(sa[i])とS.substr(sa[i+1])のLCP;
        lcp=vi(N);
        vi rank(N);
        rep(i,N)rank[sa[i]]=i;
        for(int i=0,h=0;i<N;i++){
            if(rank[i]+1<N){
                for(int j=sa[rank[i]+1];max(i,j)+h<N&&S[i+h]==S[j+h];h++);
                lcp[rank[i]]=h;
                if(h>0)h--;
            }
        }
    }
};


struct node{
    ll l,r,w;//SAの[l,r)に所属する、文字数w分のかたまり。
    vector<int> to;
    node(ll l, ll r,ll w): l(l),r(r),w(w) {}
};
void solve(){
    ll n,k;cin >> n >> k;
    vector<int> a(n);rep(i,n)cin >> a[i];
    auto s=SuffixArray(a);
    s.construct_lcp();
    /*rep(i,n)cout << s.sa[i] <<" ";cout << endl;
    rep(i,n)cout << s.lcp[i] <<" ";cout << endl;*/
    vector<node> tree;
    tree.emplace_back(0,n,0);
    stack<int> st;
    st.push(0);
    int nw=0;
    rep(i,n){
        int w=n-s.sa[i];//何文字?
        if(nw<w){//今見ている文字列になるようにstackに追加する。
            st.push(tree.size());//頂点番号
            tree.emplace_back(i,0,w-nw);
            nw=w;
        }
        int tow=s.lcp[i];//何文字までstackを縮める?
        while(tow<nw){
            int ti=st.top();st.pop();
            nw-=tree[ti].w;
            tree[ti].r=i+1;
            if(nw<tow){
                tree[ti].w-=tow-nw;
                st.push(tree.size());
                tree.emplace_back(tree[ti].l,0,tow-nw);
                nw+=tow-nw;
            }
            tree[st.top()].to.emplace_back(ti);
        }
    }
    return;
    /*for(auto p:tree){
        cout << p.l <<" " << p.r <<" " << p.w << endl;
        for(auto z:p.to)cout << z <<" "; cout << endl;
    }*/
    int p=0; 
    ll ans=0,height=0;
    auto dfs=[&](auto &self,ll i,ll h)->void {
        ll cnt=(tree[i].r-tree[i].l)*tree[i].w;
        //cout << cnt << endl;
        if(p<k&&p+cnt>=k){
            ans=tree[i].l;
            height=h+(k-p+tree[i].r-tree[i].l-1)/(tree[i].r-tree[i].l);
        }
        p+=cnt;
        h+=tree[i].w;
        for(auto p:tree[i].to){
            self(self,p,h);
        }
    };
    dfs(dfs,0,0);
    ans=s.sa[ans];
    //cout << ans <<" " << height << " " << p << endl;
    rep(i,height)cout << a[i+ans] <<" ";cout << endl;
}

int main(){
    ll t;cin >> t;
    while(t--)solve();
}
0