云斗 E. 开上我心爱的新能源车
芙芙的超级矩阵蛋糕 - 云斗补题域 - 题目详情 - 云斗学院 (yundouxueyuan.com)
PS:被 hack 了。
给出一种思路。我觉得T2贪心就可以吧,完了T1反悔贪就可以。
T2:首先对于一行来说,在忽略0的情况下,如果他是单调不降的,那么这一行就一定可以变成单调不降的(因为单调不降,0可以直接等于其两边的值)。同理如果在忽略下不行,那就一定不行。因为尽量选A,所以行能变,就变。
对于能变A行里的0,因为要保证单调,所以它的范围就是左右两个非0值。而对于不能变A的行的0,就把范围扩到 1~INF,好给后面凑列。
先扫一遍行确定单调。再扫一遍给对应0加上范围即可。
对于列,如果一个列里面有两个不同常数,那么一定统计不了。对于可能能统计的情况,如果是常数列(无0,全相同),直接统计入 B;
如果是全0列,设 \(l = 0,r = inf\),用这一列的 0 的范围去缩小 \(l,r\) 范围,如果可以使 l > r 说明没法得到一个共同的数,形成常数列。
如果是含0也含同一个常数。看看常数是否在每个0范围之内即可。
注意,0的范围是已经保证了A最大了。只要在这个范围内得到的最大的B就是答案。
这题就是调起来麻烦。像个模拟。
hack 数据
2 3
8 8 5
0 0 0
1 0
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <map>
#include <unordered_map>
#include <vector>
#include <chrono>
#define x first
#define y second
using namespace std;
typedef pair<int, int> PII;
const int N = 100010, M = 1000010, INF = 0x3f3f3f3f;
int n, m;
unordered_map<int, unordered_map<int, int>> id;
vector<PII> e[N];
vector<int> res, g[N];
int st_h[N], st_l[N];
int cnt1, cnt2, cnt;
int lss[M], rss[M];
int read()
{
int x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9')
{
if (ch == '-') f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9')
x = 10 * x + ch - '0', ch = getchar();
return x * f;
}
int main()
{
// freopen("2.in", "r", stdin);
// freopen("2.ans", "w", stdout);
cin >> n >> m;
for (int i = 1; i <= n; i ++ )
{
bool flag = 0;
int last = 0;
g[i].push_back(1);
for (int j = 1; j <= m; j ++ )
{
g[i].push_back(read());
id[i][j] = ++ cnt;
if (g[i][j] && g[i][j] < last) flag = 1;
last = max(g[i][j], last);
}
if (flag == 0)
{
cnt1 ++ ;
st_h[i] = true;
}
int lasts = 0;
for (int j = 1; j <= m; j ++ )
{
if (g[i][j]) lasts = g[i][j];
else lss[id[i][j]] = lasts;
if (g[i][j]) lasts = g[i][j];
else rss[id[i][j]] = lasts;
}
lasts = INF;
for (int j = m; j; j -- )
{
if (g[i][j]) lasts = g[i][j];
else rss[id[i][j]] = lasts;
}
}
for (int j = 1; j <= m; j ++ )
{
bool flag = 0, flag2 = 0;
int last = 0, ls = g[1][j];
for (int i = 1; i <= n; i ++ )
{
if (g[i][j] == 0)
{
if (st_h[i]) e[j].push_back({lss[id[i][j]], rss[id[i][j]]});
else e[j].push_back({0, INF});
}
else
{
if (last == 0) last = g[i][j];
if (last != g[i][j]) flag = 1;
}
if (ls != g[i][j] || g[i][j] == 0) flag2 = true;
}
//
if (flag2 == 0) cnt2 ++ ;
else if (flag == 0)
{
if (last)
{
st_l[j] = 1; // 有限制
// cout << j << ' ' << last << endl;
e[j].push_back({-INF, last});
}
res.push_back(j);
}
}
for (int i : res)
{
auto res = e[i];
sort(res.begin(), res.end());
if (st_l[i]) // 有常限制
{
bool flag = true;
int k = res[0].y;
int len = res.size();
// cout << k << endl;
for (int i = 1; i < len; i ++ )
{
// cout << res[i].x << ' ' << res[i].y << endl;
if (res[i].x > k) flag = false;
if (res[i].y < k) flag = false;
}
if (flag) cnt2 ++ ;
}
else // 无限制
{
int l = 0, r = INF;
bool flag = true;
for (auto i : res)
{
l = max(l, i.x);
r = min(r, i.y);
if (r < l) flag = false;
}
if (flag) cnt2 ++ ;
}
}
cout << cnt1 << ' ' << cnt2 << endl;
return 0;
}
/*
4 3
3 0 0
1 0 2
2 1 0
1 0 2
3 0
*/