結果
| 問題 |
No.3368 トッピング
|
| コンテスト | |
| ユーザー |
noya2
|
| 提出日時 | 2025-11-10 02:36:59 |
| 言語 | C++23 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 135 ms / 2,000 ms |
| コード長 | 2,154 bytes |
| コンパイル時間 | 3,023 ms |
| コンパイル使用メモリ | 281,956 KB |
| 実行使用メモリ | 7,720 KB |
| 最終ジャッジ日時 | 2025-11-17 20:44:41 |
| 合計ジャッジ時間 | 4,701 ms |
|
ジャッジサーバーID (参考情報) |
judge5 / judge4 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 14 |
ソースコード
/*
答えで二分探索
dpdiff[i][j] : 位置 i まで見て,直前の種類が j で,次は j 以外と決めたときの,ペナルティが発生しない回数の最小値
dpsame[i][j] : 位置 i まで見て,直前の種類が j で,次も j と決めたときの,ペナルティが発生しない回数の最小値
next dp で次元を減らす
dpdiff は top2 しか持たなくて良い
*/
#include<bits/stdc++.h>
using namespace std;
const int iinf = 1001001007;
bool chmin(auto &a, auto b){ return a > b ? a = b, 1 : 0; }
bool chmax(auto &a, auto b){ return a < b ? a = b, 1 : 0; }
struct top2 {
int v1, i1;
int v2, i2;
top2 () : v1(iinf), i1(-1), v2(iinf), i2(-1) {}
void upd(int v, int i){
if (v < v1){
v2 = v1;
i2 = i1;
v1 = v;
i1 = i;
}
else if (v < v2){
v2 = v;
i2 = i;
}
}
int get(int except){
return (i1 == except ? v2 : v1);
}
};
int main(){
cin.tie(0)->sync_with_stdio(0);
int n, m, c, x; cin >> n >> m >> c >> x;
vector a(n,vector<int>(m));
for (int i = 0; i < n; i++){
for (int j = 0; j < m; j++){
cin >> a[i][j];
}
}
int le = -iinf, ri = iinf;
while (ri - le > 1){
int md = midpoint(le, ri);
top2 dpdiff;
vector<int> dpsame(m,iinf);
dpdiff.upd(0,-1);
for (int i = 0; i < n; i++){
top2 ndpdiff;
vector<int> ndpsame(m,iinf);
for (int j = 0; j < m; j++){
// diff
if (a[i][j] >= md){
ndpdiff.upd(dpdiff.get(j)+1,j);
}
// same
if (a[i][j] >= md+c){
ndpdiff.upd(dpsame[j],j);
chmin(ndpsame[j],dpsame[j]);
chmin(ndpsame[j],dpdiff.get(j));
}
}
swap(ndpdiff,dpdiff);
swap(ndpsame,dpsame);
}
if (dpdiff.v1 <= n-x){
le = md;
}
else {
ri = md;
}
}
cout << le << endl;
}
noya2