CF15D Map 题解
考虑到
一开始,预处理出以每个点为左上角的 multiset
做到一只
每次选择最小的答案,把这个矩阵能影响的点删掉,循环做即可。
比较卡常,建议使用手写懒惰删除堆代替 multiset
。
#pragma comment(linker, "/stack:200000000")
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include <bits/stdc++.h>
using namespace std;
const int N = 1005;
int n, m, a, b;
int c[N][N];
long long sum[N][N];
struct Node
{
int x, y;
long long w;
Node(int _x, int _y, long long _w): x(_x), y(_y), w(_w){}
Node() = default;
bool operator<(const Node& xx) const
{
if (w != xx.w) return w > xx.w;
if (x != xx.x) return x > xx.x;
return y > xx.y;
}
bool operator==(const Node& g) const
{
return x == g.w && y == g.y && w == g.w;
}
};
class Mymultiset
{
public:
priority_queue<Node> q1, q2;
void ins(Node x)
{
q1.push(x);
}
void del(Node x)
{
q2.push(x);
}
int sz()
{
return q1.size() - q2.size();
}
Node Top()
{
while (q2.size() && q1.top() == q2.top()) q1.pop(), q2.pop();
return q1.top();
}
void Pop()
{
while (q2.size() && q1.top() == q2.top()) q1.pop(), q2.pop();
q1.pop();
}
};
Mymultiset mt;
int LG2[N];
class ST
{
public:
int f[11][N];
void Init(int *c)
{
memset(f, 0x3f, sizeof f);
for (int i = 1; i <= m; i++) f[0][i] = c[i];
for (int j = 1; j <= LG2[m]; j++)
{
for (int i = 1; i + (1 << j) - 1 <= m; i++)
{
f[j][i] = min(f[j - 1][i], f[j - 1][i + (1 << (j - 1))]);
}
}
}
int query(int l, int r)
{
int p = LG2[r - l + 1];
return min(f[p][l], f[p][r - (1 << p) + 1]);
}
}s[N];
bool vis[N][N];
signed main()
{
ios::sync_with_stdio(0), cin.tie(0);
for (int i = 2; i < N; i++) LG2[i] = LG2[i / 2] + 1;
cin >> n >> m >> a >> b;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
cin >> c[i][j];
sum[i][j] = sum[i][j - 1] + sum[i - 1][j] - sum[i - 1][j - 1] + c[i][j];
}
s[i].Init(c[i]);
}
vector<Node> res;
for (int j = 1; j <= m - b + 1; j++)
{
multiset<int> sts;
for (int i = 1; i <= a; i++) sts.insert(s[i].query(j, j + b - 1));
for (int i = 1; i <= n - a + 1; i++)
{
long long su = sum[i + a - 1][j + b - 1] - sum[i + a - 1][j - 1] - sum[i - 1][j + b - 1] + sum[i - 1][j - 1];
mt.ins(Node(i, j, su - 1LL * (*sts.begin()) * a * b));
sts.erase(sts.find(s[i].query(j, j + b - 1)));
if (i + a <= n) sts.insert(s[i + a].query(j, j + b - 1));
}
}
while (mt.sz())
{
auto u = mt.Top();
mt.Pop();
if (vis[u.x][u.y]) continue;
vis[u.x][u.y] = 1;
res.emplace_back(u);
for (int i = max(1, u.x - a + 1); i <= u.x + a - 1; i++)
{
for (int j = max(1, u.y - b + 1); j <= u.y + b - 1; j++) vis[i][j] = 1;
}
}
cout << res.size() << "\n";
for (auto &[x, y, z] : res)
{
cout << x << " " << y << " " << z << "\n";
}
return 0;
}
分类:
题解
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现