赛时想到了这种解法但由于码力太低没摸出来...
#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快这么多(
建议别养成使用unorder_map的习惯,unorder_map的原理决定了它很容易被造数据卡掉,另外,范围不大直接用数组吧,非必要不要map,常数超级大
是的,我基本上不使用unordered_map,这题实在是超时了一个点,才改了unordered_map
一开始想到的是用multiset,后面才改成了unordered_map,没去想数组orz
multi系的我没用过不知道,但是ordered的set/map确实常数起飞,加个unordered好像常数会好一些,但是感觉很不稳定而且还是常数很大(逃)
orz