题解:CF1418F Equal Product
Jasonbenji · · 题解
题解:CF1418F Equal Product
由于条件
由于我们要对每个
观察到
-
-
- 隐藏条件
b\mid y_1 即y_1 是b 的倍数。
有用的
:::warning[麻烦解法]
判定是否存在是经典的,可以离线后按照其中一个维度排序,利用扫描线的技巧处理。但由于该做法是基于判定问题等价于数量查询问题,而数量查询问题可差分成若干个左端点为
显然没有人想写主席树上二分,所以观察性质。会发现第二个条件与
这是容易的,每次加入或删除一个 map<int, int> all_b,map 的代价。
之后就简单了,在每个 all_b.lower_bound() 操作查询在
总复杂度为
:::success[AC code]
#include <bits/stdc++.h>
using namespace std;
constexpr int N = 2e5;
constexpr int M = 2e5;
int n, m;
vector<int> vec[max(N, M) + 1];
long long l, r;
map<int, int> all_b;
inline void add(int y_1) {
if (1 <= y_1 && y_1 <= m) {
for (int b : vec[y_1])
all_b[b]++;
}
}
inline void sub(int y_1) {
if (1 <= y_1 && y_1 <= m) {
for (int b : vec[y_1])
if (!--all_b[b])
all_b.erase(b);
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
// freopen("test.out", "w", stdout);
cin >> n >> m >> l >> r;
for (int i = 1; i <= max(n, m); i++)
for (int j = i; j <= max(n, m); j += i)
vec[j].push_back(i);
all_b.emplace(INT_MAX, 114514);
int min_y_1 = m + 1, max_y_1 = m;
for (int x_1 = 1; x_1 <= n; x_1++) {
int new_min_y_1 = max(1LL, min((l + x_1 - 1) / x_1, m + 1LL));
int new_max_y_1 = min(r / x_1, m + 0LL);
// cerr << min_y_1 << ' ' << max_y_1 << " -> ";
// cerr << new_min_y_1 << ' ' << new_max_y_1 << '\n';
while (min_y_1 > new_min_y_1)
add(--min_y_1);
while (max_y_1 < new_max_y_1)
add(++max_y_1);
while (min_y_1 < new_min_y_1)
sub(min_y_1++);
while (max_y_1 > new_max_y_1)
sub(max_y_1--);
// cerr << "go ok\n";
array<int, 4> ans = array<int, 4>{-1, -1, -1, -1};
for (int a : vec[x_1]) {
int X = x_1 / a;
long long min_b = a + 1, max_b = n / X;
auto it = all_b.lower_bound(min_b);
if (it -> first <= max_b) {
auto b = it -> first;
int y_1 = max_y_1 / b * b;
int Y = y_1 / b;
int x_2 = X * b, y_2 = Y * a;
ans = array<int, 4>{x_1, y_1, x_2, y_2};
break;
}
}
if (ans[0] == -1)
cout << -1 << '\n';
else
cout << ans[0] << ' ' << ans[1] << ' ' << ans[2] << ' ' << ans[3] << '\n';
}
return 0;
}
:::