ABC445D Reconstruct Chocolate

d---reconstruct-chocolate">D - Reconstruct Chocolate

1. 题意梗概

给定 NN 个矩形巧克力碎片的尺寸 (hi,wi)(h_i, w_i),这些碎片是通过对一个 H×WH \times W 的大矩形进行 N−1N-1 次操作得到的;操作为切下一块放在桌上,手里留一块。求出每个碎片的左上角坐标 (xi,yi)(x_i, y_i)。

Constraints

  • 1≤H≤1091 \leq H \leq 10^9
  • 1≤W≤1091 \leq W \leq 10^9
  • 2≤N≤2×1052 \leq N \leq 2\times 10^5
  • 1≤hi≤H1 \leq h_i \leq H
  • 1≤wi≤W1 \leq w_i \leq W

2. 逻辑推导

这个 N≤2e5N \leq 2e5,就没法暴力了。

我们分析这个操作,每一次操作,都会让手上现有的巧克力切成两块,而且是沿着水平或者垂直线切的,这意味这什么?

这意味着切完之后这两块巧克力,要么 hh 相等,要么 ww 相等。

所以我们可以采用贪心模拟的策略,由于从最后一块开始拼装处理起来很麻烦,所以我们考虑从完整的巧克力开始切,考虑剩余的部分可以塞下谁。

维护当前剩余矩形的左上角坐标 (cx, cy) 和剩余尺寸 (ch, cw)。

  1. 若存在碎片高度等于 ch,则该碎片填在当前列,cy 向右移动该碎片的宽度,cw 减少。

  2. 若存在碎片宽度等于 cw,则该碎片填在当前行,cx 向下移动该碎片的高度,ch 减少。

然后就是快速查询的问题了,由于这题的 H,W≤1e9H, W \le 1e9,但是 N≤2e5N \leq 2e5,最直接的想法就是离散化,然后二分查询。

因为标准离散化写起来比较麻烦(苍天可鉴,代码复杂度高),我这里就偷懒采用 mapmap 作为离散化工具。

因为同一高度或者宽度的巧克力可能有很多,所以我开了一个 map< int, set< int > > 来存储,第一维是具体的值,第二位是符合条件的值的下标。

找到之后再通过 erase 函数删掉就行了,代码写起来很优雅,如下。

3. 代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <bits/stdc++.h>
using namespace std;
using ll = long long;

const int maxn = 2e5 + 50;

struct Point { ll x, y; } ans[maxn];

map< int, set< int > > hh, ww;
ll h[maxn], w[maxn];
ll H, W;
int n;

void solve( )
{
cin >> H >> W >> n;
for( int i = 1; i <= n; ++ i )
{
cin >> h[i] >> w[i];
hh[ h[i] ].insert( i );
ww[ w[i] ].insert( i );
}

ll cx = 1, cy = 1;
ll ch = H, cw = W;

for( int i = 1; i <= n; ++ i )
{
int idx = -1;
// 先判断高度有没有合适的
if( hh.count( ch ) && !hh[ch].empty( ) )
{
idx = *hh[ch].begin( );
ans[idx] = { cx, cy };
cy += w[idx];
cw -= w[idx];
}
// 如果没有高度合适的,就找长度合适的
else if( ww.count( cw ) && !ww[cw].empty( ) )
{
idx = *ww[cw].begin( );
ans[idx] = { cx, cy };
cx += h[idx]; ch -= h[idx];
}
// 如果找到了能用的,就同步移除已经使用的碎片
if( idx != - 1 )
{
hh[h[idx]].erase( idx );
ww[w[idx]].erase( idx );
}
}
// 输出
}

ABC445D Reconstruct Chocolate
http://miqiu.space/posts/e79ccf0c/
作者
Miqiu
发布于
2026年2月14日
许可协议