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;
}

 

posted @ 2020-11-16 19:44  huangxuanao  阅读(229)  评论(0)    收藏  举报