Codeforces Round #683 (Div. 1, by Meet IT)题解
A. Knapsack
题解:将物品按质量从大到小排序,遍历所有物品
如果当前背包中物品质量之和大于 $⌈\dfrac{W}{2}⌉$,则为一组合法解
否则将当前物品加入背包
因为如果当前 $C<⌈\dfrac{W}{2}⌉$ ,则当前物品质量也 $<⌈\dfrac{W}{2}⌉$ ,加入不会使$C>W$
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int n, ans[200011], cnt;
ll w;
struct Data {
ll s;
int id;
} a[200011];
bool cmp(Data p1, Data p2) {
return p1.s > p2.s;
}
void solve() {
scanf("%d%lld", &n, &w);
for(int i = 1; i <= n; i++) {
scanf("%lld", &a[i].s);
a[i].id = i;
}
sort(a+1, a+n+1, cmp); cnt = 0;
ll sum = 0, mid = (w + 1) / 2;
for(int i = 1; i <= n; i++) {
if(a[i].s >= mid && a[i].s <= w) {
cout << 1 << endl << a[i].id << endl;
return;
}
if(a[i].s < mid) {
sum += a[i].s;
ans[++cnt] = a[i].id;
if(sum >= mid) {
cout << cnt << endl;
for(int i = 1; i <= cnt; i++) cout << ans[i] << ' ';
cout << endl;
return;
}
}
}
cout << -1 << endl;
}
int main() {
int T = 1; scanf("%d", &T);
while(T--) solve();
return 0;
}
B. Catching Cheaters
题解:注意到$LCS$长一位对答案贡献为$4-2=2$,子串长一位对答案贡献的$-1$
于是直接DP即可
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int n, m, dp[5011][5011], ans;
char a[5011], b[5011];
void solve() {
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++) cin >> a[i];
for(int i = 1; i <= m; i++) cin >> b[i];
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++) {
if(a[i] == b[j]) dp[i][j] = dp[i-1][j-1] + 2;
dp[i][j] = max(dp[i][j], dp[i-1][j] - 1);
dp[i][j] = max(dp[i][j], dp[i][j-1] - 1);
ans = max(ans, dp[i][j]);
}
cout << ans << endl;
}
int main() {
int T = 1;
while(T--) solve();
return 0;
}
C. Xor Tree
题解:建立01trie
我们把问题转化为删掉若干个数,使得这个图中只有一个联通块
我们发现对于任意节点,若左儿子和右儿子的$siz$都大于$1$,则会形成两个子图
所以我们必须使某一儿子的$siz=1$,DP(或贪心)解决即可
#include <bits/stdc++.h>
using namespace std;
int n, s, cnt, dig[31], rt, tot;
struct node {
int son[2], siz;
} a[6000011];
void ins(int &k, int w) {
if(!k) k = ++tot;
a[k].siz++;
if(!w) return;
ins(a[k].son[dig[w]], w-1);
}
int f[6000011];
void dfs(int k, int w) {
if(!k || !w) return;
dfs(a[k].son[0], w-1);
dfs(a[k].son[1], w-1);
f[k] = f[a[k].son[0]] + f[a[k].son[1]];
a[k].siz = a[a[k].son[0]].siz + a[a[k].son[1]].siz;
if(a[a[k].son[0]].siz > 1 && a[a[k].son[1]].siz > 1) {
if(a[a[k].son[0]].siz > a[a[k].son[1]].siz) {
a[k].siz -= a[a[k].son[1]].siz - 1;
f[k] += a[a[k].son[1]].siz - 1;
}
else {
a[k].siz -= a[a[k].son[0]].siz - 1;
f[k] += a[a[k].son[0]].siz - 1;
}
}
}
int main() {
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
scanf("%d", &s); cnt = 0;
memset(dig, 0, sizeof(dig));
while(s) {
dig[++cnt] = s % 2;
s /= 2;
}
ins(rt, 30);
}
dfs(rt, 30);
cout << f[rt] << endl;
return 0;
}

浙公网安备 33010602011771号