思路:前缀和+双指针
代码:
#include <bits/stdc++.h>
using namespace std;
using i64 = int64_t;
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
cout << fixed << setprecision(20);
int t = 1;
for (int ti = 0; ti < t; ti += 1) {
int n, W;
cin >> n >> W;
vector<i64> w(n + 1), d(n + 1);
for (int i = 1; i <= n; i += 1) {
cin >> w[i];
w[i] += w[i - 1];
}
for (int i = 1; i <= n; i += 1) {
cin >> d[i];
d[i] += d[i - 1];
}
i64 ans = -1e18, mn = 1e18;
for (int i = 1, j = 0; i <= n; i += 1) {
while (w[i] - w[j] >= W) {
mn = min(mn, d[j]);
j += 1;
}
ans = max(ans, d[i] - mn);
}
cout << ans;
}
}
思路:首先如果有0,1,2……,x-1,那么有2^x种选择方案.考虑二进制拆分,首先构造出最高位的答案2^x种.然后从大到小遍历每一位,如果第i位是1,就在序列最后添加一个i,不难发现每添加一次数会让答案增加2^i,而且因为添加的数是递减的,所以不会相互干扰.
代码:
void solve(){
int n;
cin >> n;
int t = __lg(n);
vector<int> ans;
for(int i = 0; i < t; i++){
ans.push_back(i);
}
for(int i = t - 1; i >= 0; i--){
if (n >> i & 1){
ans.push_back(i);
}
}
cout << ans.size() << '\n';
for(auto x : ans) cout << x << ' ';
cout << '\n';
}