方法一:二分答案

估一下二分的范围,a + b <= 2E9,那么n二分的上界限定到ceil(sqrt(2E9))即可,我这里直接取了45000,它的平方也不会爆int;由于a + b > 0,那么二分的下界即为1。

思考check函数,观察样例和说明,发现边长为n的棋盘,最多可以同时放下一种数量为ceil((n * n) / 2)的棋子和另一种数量为floor((n * n) / 2)的棋子。不妨分别记为cnt1和cnt2(显然cnt1 >= cnt2)。当然对于读入的数据a和b,我们也要保证a >= b,然后check的时候判断cnt1 >= a且cnt2 >= b即可。

#include <iostream>

void solve(){
  int a, b;
  std::cin >> a >> b;

  if(b > a){
    std::swap(a, b);
  }

  auto check = [&](int x){
    int sum = x * x;
    int cnt1 = (sum + 1) / 2;
    int cnt2 = sum / 2;
    return cnt1 >= a && cnt2 >= b;
  };

  int l = 1, r = 45000;
  while(l < r){
    int mid = (l + r) >> 1;
    if(check(mid)){
      r = mid;
    }else{
      l = mid + 1;
    }
  }

  std::cout << l << "\n";
}

int main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(nullptr);
  std::cout.tie(nullptr);

  int T = 1;
  std::cin >> T;

  for(int Ti = 0; Ti < T; Ti++){
    solve();
  }

  return 0;
}

方法二:打表+二分查找

预处理出边长从1到45000的棋盘所能最多同时容纳两种棋子的数量,对于每组数据,二分查找到第一个大于等于{a, b}的下标就是答案,可以直接使用std::lower_bound。

#include <iostream>
#include <vector>
#include <array>
#include <algorithm>

std::vector<std::array<int, 2>> v(45001);

void solve(){
  int a, b;
  std::cin >> a >> b;

  if(b > a){
    std::swap(a, b);
  }

  std::cout << std::lower_bound(v.begin(), v.end(), std::array{a, b}) - v.begin() << "\n";
}

int main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(nullptr);
  std::cout.tie(nullptr);

  for(int i = 1; i <= 45000; i++){
    v[i] = {(i * i + 1) / 2, (i * i) / 2};
  }

  int T = 1;
  std::cin >> T;

  for(int Ti = 0; Ti < T; Ti++){
    solve();
  }

  return 0;
}

方法三:通过sqrt直接算

通过a和b中的较大值,记为max,可以大致将答案n设为ceil(sqrt(max + ((max & 1) ? max - 1 : max)})),然后再根据是否满足条件对这个答案n进行微调。

#include <iostream>
#include <cmath>

void solve(){
  int a, b;
  std::cin >> a >> b;

  if(b > a){
    std::swap(a, b);
  }

  int n = std::ceil(std::sqrt(1. * (a + ((a & 1) ? a - 1 : a))));
  while((n * n + 1) / 2 < a || (n * n) / 2 < b){
    n++;
  }

  std::cout << n << "\n";
}

int main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(nullptr);
  std::cout.tie(nullptr);

  int T = 1;
  std::cin >> T;

  for(int Ti = 0; Ti < T; Ti++){
    solve();
  }

  return 0;
}