結果
問題 |
No.3188 K-th Lexmin
|
ユーザー |
|
提出日時 | 2025-06-21 18:35:28 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
TLE
|
実行時間 | - |
コード長 | 6,113 bytes |
コンパイル時間 | 2,589 ms |
コンパイル使用メモリ | 216,432 KB |
実行使用メモリ | 16,068 KB |
最終ジャッジ日時 | 2025-06-21 18:35:40 |
合計ジャッジ時間 | 9,482 ms |
ジャッジサーバーID (参考情報) |
judge5 / judge2 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 1 |
other | TLE * 1 -- * 46 |
ソースコード
#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); } } /*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(); }