[题解]CF1819B The Butcher
思路
首先发现对于每一次切割,长和宽只会变化一次。
所以,答案最多只会有两种情况(其中 \(S\) 为矩形的面积):
- \((\max\{a_i\},\frac{S}{\max\{a_i\}})\),其中需要满足 \(S \bmod \max\{a_i\} = 0\)。
- \((\frac{S}{\max\{b_i\}},\max\{b_i\})\),其中需要满足 \(S \bmod \max\{b_i\} = 0\)。
那么,直接判断这两种情况即可。
首先一直将长与当前目标长一样的矩形丢进去,然后将宽与当前目标宽一样的矩形丢进去。
注意在更新长宽的时候,目标长宽也会发生变化,需要时时更新。
在目标长宽其中有一个更新为 \(0\) 时,表示此情况成立;如果在更新过程中,发现没有任何一个矩形能够放进去了,表示此情况不成立。
为了代码的可读性,我们可以将 \((a_i,b_i)\) 用两个数组存起来,分别按照 \(a_i > a_j\) 与 \(b_i > b_j\) 进行排序。
Code
#include <bits/stdc++.h>
#define fst first
#define snd second
#define int long long
#define re register
using namespace std;
typedef pair<int,int> pii;
const int N = 2e5 + 10;
int T,n,s;
bool vis[N];
struct square{
int a;
int b;
int id;
}arr[N],brr[N];
inline int read(){
int r = 0,w = 1;
char c = getchar();
while (c < '0' || c > '9'){
if (c == '-') w = -1;
c = getchar();
}
while (c >= '0' && c <= '9'){
r = (r << 3) + (r << 1) + (c ^ 48);
c = getchar();
}
return r * w;
}
inline bool check(int a,int b){
int ida = 1,idb = 1;
for (re int i = 1;i <= n;i++) vis[i] = false;
while (a > 0 && b > 0){
while (ida <= n && vis[arr[ida].id]) ida++;
int idxa = ida,idxb = idb;
while (ida <= n && arr[ida].a == a){
vis[arr[ida].id] = true;
b -= arr[ida].b;
ida++;
}
while (idb <= n && vis[brr[idb].id]) idb++;
while (idb <= n && brr[idb].b == b){
vis[brr[idb].id] = true;
a -= brr[idb].a;
idb++;
}
if (idxa == ida && idxb == idb) return false;
}
if (!a || !b) return true;
return false;
}
signed main(){
T = read();
while (T--){
int A = 0,B = 0,s = 0,num = 0;
vector<pii> v;
n = read();
for (re int i = 1;i <= n;i++){
arr[i].a = brr[i].a = read();
arr[i].b = brr[i].b = read();
arr[i].id = brr[i].id = i;
s += arr[i].a * arr[i].b;
A = max(A,arr[i].a);
B = max(B,arr[i].b);
}
sort(arr + 1,arr + n + 1,[](const square &a,const square &b){
if (a.a != b.a) return a.a > b.a;
return a.b > b.b;
});
sort(brr + 1,brr + n + 1,[](const square &a,const square &b){
if (a.b != b.b) return a.b > b.b;
return a.a > b.a;
});
if (s % A == 0 && check(A,s / A)){
num++;
v.push_back({A,s / A});
}
if (s % B == 0 && check(s / B,B)){
if (v.empty() || (v[0].fst != s / B || v[0].snd != B)){
num++;
v.push_back({s / B,B});
}
}
printf("%lld\n",num);
for (auto p:v) printf("%lld %lld\n",p.fst,p.snd);
}
return 0;
}

浙公网安备 33010602011771号