题解:P13647 [NOISG 2016] Fabric
stripe_python · · 题解
模拟赛 T4。笔者在赛时得到了一个
先考虑
如图,对于一个右下角在
然后带上面积限制。可以发现当前高度
笔者的赛时想法是用一堆线段树来维护这些连续段,或者离线以后整一堆树状数组,没调出来失败了。
有这样一个想法:对于同一行
然而我们发现
接下来是很巧妙的一步:注意到
:::info[代码]
const int N = 2005;
int n, m, k, a[N][N], h[N][N];
bool vis[N][N];
int64 f[N], cnt[N];
vector<pair<int, int>> vec[N];
struct node {
int l[N], r[N];
int64 merge(int x) {
int64 res = 0;
int a = x - l[x - 1], b = r[x + 1] - x, c;
cnt[a]--, cnt[b]--, res -= f[a] + f[b];
r[l[x - 1]] = r[x + 1], l[r[x + 1]] = l[x - 1];
return c = r[x + 1] - l[x - 1] + 1, cnt[c]++, res += f[c];
}
int64 mergel(int x) {
int64 res = 0;
int a = x - l[x - 1], c;
cnt[a]--, res -= f[a];
r[l[x - 1]] = x, l[x] = l[x - 1];
return c = x - l[x - 1] + 1, cnt[c]++, res += f[c];
}
int64 merger(int x) {
int64 res = 0;
int b = r[x + 1] - x, c;
cnt[b]--, res -= f[b];
l[r[x + 1]] = x, r[x] = r[x + 1];
return c = r[x + 1] - x + 1, cnt[c]++, res += f[c];
}
int64 create(int x) {return cnt[1]++, l[x] = r[x] = x, f[1];}
} l[N];
void _main() {
cin >> n >> m >> k;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) cin >> a[i][j];
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (a[i][j] == 0) h[i][j] = h[i - 1][j] + 1, vec[h[i][j]].emplace_back(i, j);
}
}
int64 res = 0, cur = 0;
for (int i = n; i >= 1; i--) {
int w = (k + i - 1) / i;
auto rebuild = [&]() -> void {
fill(f + 1, f + w, 0), cur = 0;
for (int j = w; j <= m; j++) {
f[j] = 1LL * (j - w + 1) * (j - w + 2) / 2;
cur += 1LL * cnt[j] * f[j];
}
};
if (i == n || w != (k + i) / (i + 1)) rebuild();
for (const auto& pos : vec[i]) {
int x = pos.first, y = pos.second;
if (vis[x][y - 1] && vis[x][y + 1]) cur += l[x].merge(y);
else if (vis[x][y - 1]) cur += l[x].mergel(y);
else if (vis[x][y + 1]) cur += l[x].merger(y);
else cur += l[x].create(y);
vis[x][y] = true;
}
res += cur;
} cout << res;
}
:::