1 条题解
-
0
自动搬运
来自洛谷,原作者为

hs_black
Go for broke搬运于
2025-08-24 22:16:04,当前版本为作者最后更新于2020-01-26 12:33:11,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
[POI2016]Korale题解
不妨把题目的分为两问
Part1: 求出第k小的项链组合价值
思路类似超级钢琴, 先将价值排序, 用二元组 描述前i个数选出若干数和为sum(必选第i个数), 利用小根堆不断取出堆顶, 并把和加入堆中. 这种方法可以将所有情况不重不漏遍历且具有单调性, 时间复杂度
Part2: 求出所用珠子集合
设上一问求出的答案为ans, 排名小于等于k且和为ans的个数为cnt
爆搜: 从前向后取数, 每次尽量取靠前的数, 从而保证字典序最小, 取数可以用线段树维护区间最小值, 用st表也是可以的, 因为取得集合排名一定小于等于k, 所以最多选出k次, 复杂的
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <queue> #include <algorithm> #define ll long long using namespace std; const int N = 1005000; template <typename T> void read(T &x) { x = 0; bool f = 0; char c = getchar(); for (;!isdigit(c);c=getchar()) if (c=='-') f=1; for (;isdigit(c);c=getchar()) x=x*10+(c^48); if (f) x=-x; } template <typename T> void write(T x) { if (x < 0) putchar('-'), x = -x; if (x >= 10) write(x / 10); putchar('0' + x % 10); } int n, k; int a[N], b[N]; struct node { ll sum, i; bool operator < (const node &i) const { return sum > i.sum; } }; priority_queue <node> q; ll ans, cnt; #define p1 p << 1 #define p2 p << 1 | 1 int mn[N<<2]; inline int Mn(int a, int b) {return a > b ? b : a;} void build(int l, int r, int p) { if (l == r) return mn[p] = a[l], void(); int mid = (l + r) >> 1; build(l, mid, p1), build(mid + 1, r, p2); mn[p] = Mn(mn[p1], mn[p2]); } int query(int l, int r, int p, int ql, ll x) { if (ql <= l) { if (mn[p] > x) return 0; if (l == r) return l; } int mid = (l + r) >> 1; if (ql <= mid) { int t = query(l, mid, p1, ql, x); if (t) return t; } return query(mid + 1, r, p2, ql, x); } int top, st[N]; void dfs(int l, ll res) { if (!res) { cnt--; if (!cnt) { cout << ans << endl; for (int i = 1;i <= top; i++) write(st[i]), putchar(' '); exit(0); } } for (int i = l + 1;i <= n; i++) { i = query(1, n, 1, i, res); if (!i) return; st[++top] = i; dfs(i, res - a[i]); top--; } } int main() { read(n), read(k); k--; if (k == 0) { cout << 0 << endl; return 0; } for (int i = 1;i <= n; i++) read(a[i]), b[i] = a[i]; sort(b + 1, b + n + 1); q.push((node){b[1], 1}); for (int i = 1;i <= k; i++) { node tmp = q.top(); q.pop(); if (tmp.sum == ans) cnt++; else ans = tmp.sum, cnt = 1; if (tmp.i == n) continue; tmp.i++, tmp.sum += b[tmp.i]; q.push(tmp); tmp.sum -= b[tmp.i-1]; q.push(tmp); } build(1, n, 1); dfs(0, ans); return 0; }
- 1
信息
- ID
- 4981
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 5
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者