二分答案解法

虾虎遨游直至AC(A1m233) 发表于 1年前 · 关联问题 Chronosphere Hacker

赛时想到了这种解法但由于码力太低没摸出来...

#include<bits/stdc++.h> #include<unordered_map> using namespace std; #define int long long int n, m; vector<vector<int>> mp; vector<int>a; int e; bool check(int mid) { int mex = 0; unordered_map<int, int> s; int prev = 0; for (int i = 1; mid + i - 1 <= n; i++)//i为左端点 { if (i == 1) { for (int j = i; j <= mid + i - 1; j++)s[a[j]]++;//将范围内的数置入集合 } else { s[a[i - 1]]--; prev = a[i - 1]; s[a[mid + i - 1]]++; } //其中mid+i-1是右端点 for (int j = 0; j <= mid; j++) { if (!s[j]) { mex = max(mex, j); if (mex == e)return true; break; } } } return mex == e; } void solve() { cin >> n >> m; mp.resize(n + 1, vector<int>(m + 1)); for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { cin >> mp[i][j]; } } a.resize(n + 1); map<int, int> b; for (int i = 1; i <= n; i++) { set<int> s; for (int j = 1; j <= m; j++)s.insert(mp[i][j]); for (int j = 0; j <= m; j++) { if (!s.count(j)) { a[i] = j; b[j]++; break; } } } for (int i = 0; i <= n; i++) { if (!b.count(i)) { e = i; break; } } //二分答案 int l = e, r = n; while (l < r) { int mid = l + r >> 1; if (check(mid))r = mid; else l = mid + 1; } cout << l << '\n'; } signed main() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); int tt = 1; //cin >> tt; while (tt--)solve(); return 0; }

其实是懒得优化成这种类似滑动窗口的形式+没想到unordered_map能比multiset快这么多(

wawawa 发表于 1年前

建议别养成使用unorder_map的习惯,unorder_map的原理决定了它很容易被造数据卡掉,另外,范围不大直接用数组吧,非必要不要map,常数超级大

是的,我基本上不使用unordered_map,这题实在是超时了一个点,才改了unordered_map

一开始想到的是用multiset,后面才改成了unordered_map,没去想数组orz

lr580 发表于 1年前

multi系的我没用过不知道,但是ordered的set/map确实常数起飞,加个unordered好像常数会好一些,但是感觉很不稳定而且还是常数很大(逃)

orz