思路
第一眼背包, 但是 \(n \leq 2e5\) 和重量 $ 2^{X}, X\in[0,60)$ 。所以不能使用背包
由于重量为 $ 2^{X}$ , 很有可能与二进制有关, 于是按位贪心
开 \(65\) 个优先队列,每个优先队列里存放对应与下标相等的 \(X\) 的价值,从低位开始贪心
我们知道:
\[2^i = 2^{i-1} + 2^{i-1}, i\in[1,\infty)
\]
所以贪心完的一位剩下的再两两合成, 存到下一位
正确性:
一些细节
又要问了,如果最后剩下一个怎么办:
很简单,重量直接乘 \(2\) 就行了
之前这么写,给自己恶心坏了,一直调不出来:
int bit = 0;
while (w) {if (w & 1) {// some code here}w >>= 1, ++bit;
}
\(C++\) $ AC$ \(Code\)
#include
#define int long long
using namespace std;
const int MAXN = 2e5 + 5;
int t;
int x[MAXN], y[MAXN];
priority_queue<int> que[65];
int n, w;void solve() {int ans = 0;cin >> n >> w;for (int i = 1, x, y; i <= n; ++i) {cin >> x >> y;que[x].push(y);}for (int i = 0; i <= 60; i++) {if (((w >> i) & 1) && !que[i].empty())ans += que[i].top(), que[i].pop();// 把剩下的加入下一个队列int val = 0;while (!que[i].empty()) {int tmp = que[i].top();que[i].pop();if (!val)val += tmp;else que[i + 1].push(val + tmp), val = 0;} //如果只剩奇数个,最后一个直接把他当作重量为 2 ^ (i + 1) , 质量为w的if (val)que[i + 1].push(val);}cout << ans << '\n';
}
signed main() {ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);cin >> t;while (t--)solve();return 0;
}