Codeforces 180 E. Cubes
問題
n個の整数の列がある。それぞれの数は1以上m以下である。
この列から最大k個を取り除いて、同じ整数の続く部分の長さを最大にしたい。
同じ整数の続く部分の最大の長さを求めよ。
制約条件
n≦2*10^5
m≦10^5
k≦n
方針
長さlの区間を同じ整数だけにできるというのは、
その区間で最も多い整数をaとすると、aがl-k個以上あるということである。
値の種類ごとにバケットにわけて、インデックスを二分探索(or 尺取り)する。
インデックスの差が上の条件を満たす範囲を二分探索すればいい。
のだけれど、自分はsetを使って上の条件を使って直接尺取りした。
適切なデータ構造を使えば、最も多い整数の個数を取り出すことはO(log n)で出来るので。
また、条件を満たすかは左端を決めると単調になるので尺取りできる。
ソースコード
void run() { cin >> n >> m >> k; rep(i,n) cin >> a[i], a[i]--; set<pi> s; rep(i,m) s.insert(mp(0, i)), cnt[i] = 0; int ans = 0; for(int i = 0, j = 0; i < n-k; i++){ while(j < i) j++; while(j < n){ int c = -s.begin()->first + (a[j] == s.begin()->second); if(c < j+1 - i - k) break; set<pi>::iterator it = s.lower_bound(mp(-cnt[a[j]], a[j])); s.erase(it); s.insert(mp(-(++cnt[a[j]]), a[j])); j++; } ans = max(ans, -s.begin()->first); set<pi>::iterator it = s.lower_bound(mp(-cnt[a[i]], a[i])); s.erase(it); s.insert(mp(-(--cnt[a[i]]), a[i])); } cout << ans << endl; }