CF683div.2
C Knapsack
贪心,如果一件物品的重量 \(C\) 满足 \(\lceil \frac{W}{2}\rceil\le C\le W\),则只选这一件,排除重量比 \(W\) 大的物品,不断加重量小于等于 \(\lceil \frac{W}{2}\rceil\) 的物品,直到总重量大于等于 \(\lceil \frac{W}{2}\rceil\),如果不行则无解。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
using namespace std;
#define debug(x) cout << #x << " is " << x << endl
#define inc(i, a, b) for (int i = a; i <= b; ++i)
typedef long long ll;
const int INF = 0x3f3f3f3f;
int t, n;
ll w;
int main()
{
scanf("%d", &t);
while (t--) {
scanf("%d%lld", &n, &w);
vector<int> v;
ll x, sum = 0;
for (int i = 1; i <= n; ++i) {
scanf("%lld", &x);
if (x > w || sum >= (w + 1) / 2) continue;
else if (x >= (w + 1) / 2) { v = {i}; sum = x; }
else { sum += x; v.push_back(i); }
}
if (sum >= (w + 1) / 2) {
printf("%d\n", (int)v.size());
for (auto i : v) printf("%d ", i);
puts("");
}
else puts("-1");
}
return 0;
}
D Catching Cheaters
类似 LCS 的思想,\(dp[i][j]\) 表示第一个子串以 \(A_i\) 结尾第二个子串以 \(B_j\) 结尾的最大相似分数,则 \(dp[i][j]\) 至少为 0,每种情况下 \(dp[i][j]\) 都可以通过 \(dp[i-1][j]\) 或 \(dp[i][j-1]\) 延长一个转移过来,\(A_i=B_j\) 则 \(dp[i][j]=\max(dp[i][j], dp[i-1][j-1]+2)\),状态转移方程为:
\[dp[i][j]=\begin{cases}\max(dp[i][j],dp[i-1][j-1]+2)\quad A[i]==B[j]\\\max(dp[i-1][j],dp[i][j-1])-1\quad for\ each\ case\end{cases}
\]
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
#define debug(x) cout << #x << " is " << x << endl
#define inc(i, a, b) for (int i = a; i <= b; ++i)
typedef long long ll;
const int INF = 0x3f3f3f3f, N = 5005;
int n, m, ans;
string A, B;
int dp[N][N];
int main()
{
scanf("%d%d", &n, &m);
cin >> A >> B;
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
dp[i+1][j+1] = max(dp[i+1][j], dp[i][j+1]) - 1;
if (A[i] == B[j]) {
dp[i+1][j+1] = max(dp[i+1][j+1], max(dp[i][j], 0) + 2);
}
ans = max(ans, dp[i+1][j+1]);
}
}
printf("%d\n", ans);
return 0;
}
E Xor Tree
建一颗 trie 树,高位靠近树根,如果一个节点左子树和右子树都包含超过 1 个节点,会形成两棵树,贪心把含数少的子树删成只有一个节点,最后保留的节点尽可能地多。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
#define debug(x) cout << #x << " is " << x << endl
#define inc(i, a, b) for (int i = a; i <= b; ++i)
typedef long long ll;
const int INF = 0x3f3f3f3f, N = 2e5 + 5;
int n;
int tr[N*31][2], tot = 1;
void insert(int val) {
int p = 1;
for (int i = 30; i >= 0; --i) {
int ch = val >> i & 1;
if (!tr[p][ch]) tr[p][ch] = ++tot;
p = tr[p][ch];
}
}
int dfs(int p) {
if (!p) return 0;
if (!tr[p][0] && !tr[p][1]) return 1;
return max(dfs(tr[p][0]) + (tr[p][1] > 0), dfs(tr[p][1]) + (tr[p][0] > 0));
}
int main()
{
scanf("%d", &n);
int x;
for (int i = 1; i <= n; ++i) {
scanf("%d", &x);
insert(x);
}
printf("%d\n", n - dfs(1));
return 0;
}
posted by 2inf

浙公网安备 33010602011771号