Codeforces #323 Div. 2 D Once Again...
問題
方針
$T \geq 300$ なら $a$ を $T$ 回繰り返す列を実際に作って LIS を求める. そうでないとき,まず $300$ 回繰り返した列の LIS を求め,その間に使わなかった $T-300$ 回に含まれる整数を挟む. 挟むのは $a$ に最も多く出現するものをその回数 $\times$ $300-T$ 個選ぶのが最適.
これで正しいらしいけど理由分かってない
行列累乗でも解けるらしい.
実装
int n,T;
vector<int> a;
vector<int> lis(const vector<int> &x) {
int n = x.size();
vector<int> dp(300*300+100, inf);
for (int i = 0; i < n; i++){
*upper_bound(dp.begin(), dp.begin() + n, x[i]) = x[i];
}
auto it = lower_bound(dp.begin(), dp.begin() + n, inf);
return vector<int>(dp.begin(), it);
}
int solve(){
int dec = max(0, T-300);
T -= dec;
vector<int> b;
rep(i,T) rep(j,n) b.push_back(a[j]);
vector<int> ls = lis(b);
int freq = -1;
map<int,int> count;
rep(i,n) count[a[i]]++;
for(auto & e : count){
if(e.second > count[freq]){
freq = e.first;
}
}
return count[freq] * dec + ls.size();
}
signed main(){
while(cin >> n){
a.resize(n);
cin >> T;
rep(i,n) cin >> a[i];
cout << solve() << endl;
}
}