这个代码算法也是逆序枚举位置,对于当前位置 int x =min(n,mx/j) ,对于x进行二分upper_bound,找到第一个比x大的数后,用prev函数返回上一个位置的迭代器(无关补充:next是返回下一个位置的迭代器)。prev指向的数就是这个位置的最优数,找到后就维护sum和集合s。如果二分找不到答案,比如s的所有数都比x大,那这个排列就不能要了,直接break。另一方面,如果s的所有数都比x小,则upper_bound返回s.end(),prev后得到当前集合的最大数(set是有序容器),把这个最大数安排给这个位置。
#include <bits/stdc++.h> using namespace std; #define ll long long //# define int long long #define ull unsigned long long #define pii pair<int,int> #define double long double #define baoliu(x, y) cout << fixed << setprecision(y) << x #define endl "\n"
const int N = 2e5 + 10; const int M = 1e6 + 10; const int inf = 0x3f3f3f3f; const int mod = 998244353; const double eps = 1e-8; int n, m; int a[N];
void solve() { int n; cin >> n; int ans = 0;
for (int i = n; i >= 1; i --) { for (int pos = 1; pos <= n; pos ++) { int mx = pos * i; set<int> s; for (int j = 1; j <= n; j ++) s.insert(j);
s.erase(i);
int res = 0; bool ok = true; for (int j = n; j >= 1; j --) { if (j == pos) continue;
int x =min(n,mx/j) ; auto it = s.upper_bound(x); if (it == s.begin()) { ok = false; break; } it = std::prev(it); res += *it * j; s.erase(it); }
if (ok) ans = max(ans, res); } }
cout << ans << "\n"; }
signed main() { cin.tie(0); cout.tie(0); ios::sync_with_stdio(false);
#include <bits/stdc++.h> using namespace std; //#define ll long long; # define int long long #define ull unsigned long long #define pii pair<int,int> #define double long double #define baoliu(x, y) cout << fixed << setprecision(y) << x #define endl "\n"
const int N =510; const int M = 1e6 + 10; const int inf = 0x3f3f3f3f; const int mod = 998244353; const double eps = 1e-8; int n, m; int a[N];