Codeforces-Round-922-Div-2

注意: \color{red}{注意:} 注意: 个人博客传送门

A. Brick Wall

思路:

  • 水平的砖尽可能多,那么直接输出 n × ( m ÷ 2 ) n \times (m \div 2) n×(m÷2)​ 即可

时间复杂度: O ( 1 ) O(1) O(1)

void solve() {
    int n, m;
    std::cin >> n >> m;

    std::cout << 1LL * n * (m / 2) << "\n";
}

B. Minimize Inversions

思路:

  • 两个序列,那么只要其中一个是升序的,那么两者之和一定最少

时间复杂度: O ( n ) O(n) O(n)

void solve() {
    int n;
    std::cin >> n;

    std::vector<int> a(n), b(n);
    for (int i = 0; i < n; i++) {
        std::cin >> a[i];
    }
    for (int i = 0; i < n; i++) {
        std::cin >> b[i];
    }

    std::vector<int> p(n);
    std::iota(p.begin(), p.end(), 0);

    std::sort(p.begin(), p.end(), [&](int i, int j) {
        return a[i] < a[j];
    });

    for (int i = 0; i < n; i++) {
        std::cout << a[p[i]] << " \n"[i == n - 1];
    }
    for (int i = 0; i < n; i++) {
        std::cout << b[p[i]] << " \n"[i == n - 1];
    }
}

C. XOR-distance

思路:

  • 首先,解决本题要了解异或(xor)的性质,即:相同位为 0,不同位为 1
  • 那么要使得本题的 ∣ ( a ⊕ x ) − ( b ⊕ x ) ∣ |(a \oplus x) - (b \oplus x)| (ax)(bx) 的最小值,那么我们要明确,一定是使得 ( a ⊕ x ) (a \oplus x) (ax) ( b ⊕ x ) (b \oplus x) (bx) 的值尽可能的接近
  • 首先我们可以默认 a > b a > b a>b ,那么我们将 a a a 转换为二进制, b b b 转换为二进制,然后我们要缩小 ( a ⊕ x ) (a \oplus x) (ax) ( b ⊕ x ) (b \oplus x) (bx) 的差距,那么就需要明确,如果 a a a 的二进制表示中的某一位和 b b b 的二进制表示的某一位出现了不同,且 b i t a i > b i t b i bita_i > bitb_i bitai>bitbi 那么就需要将 a a a 的这一位与 b b b 的这一位交换(sum + 1 << i <= r的情况下)
  • 特别注意,如果从高位到低位枚举的第一个不同点出现,且这个位置的 b i t a i > b i t b i bita_i > bitb_i bitai>bitbi ,那么就要略过这一位,因为这一位换了的贡献要大于其他后面低位的所有位的贡献,这是可以证明的

推荐看一下这一篇讲解

时间复杂度: O ( l o g n ) O(logn) O(logn)

void solve() {
    i64 a, b, r;
    std::cin >> a >> b >> r;
    if (a < b) {
        std::swap(a, b);
    }
    std::array<int, 64> bita {}, bitb {};
    for (int i = 0; i <= 63; i++) {
        if (a >> i & 1) {
            bita[63 - i] = 1;
        }
        if (b >> i & 1) {
            bitb[63 - i] = 1;
        }
    }

    bool ok = false;
    i64 sum = 0;
    for (int i = 0; i <= 63; i++) {
        if (bita[i] != bitb[i]) {
            if (!ok) {
                ok = true;
            } else {
                if (bita[i] > bitb[i]) {
                    i64 t = 1LL << (63 - i);
                    if (t + sum <= r) {
                        sum += t;
                    }
                }
            }
        }
    }
    std::cout << abs((a - sum) - (b + sum)) << "\n";
}

D. Blocking Elements

snow的代码

#include <bits/stdc++.h>
using namespace std;

using ll = long long ;

void solve() {
	int n;
	cin >> n;
	
	vector<ll> a(n + 1);
	
	ll ub = 0, lb = 0;
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
		lb = max(lb, a[i]);
		ub += a[i];
	}
	
	auto check = [&](ll x) {
		ll rest = 0;
		for (int i = 1; i <= n; i++) {
			int j = i;
			ll temp = a[i];
			while (j < n && temp + a[j + 1] <= x) temp += a[++j];
			i = j + 1;
			if (i <= n) rest += a[i];
		}
		if (rest <= x) return true;
		
		rest = a[1];
		for (int i = 2; i <= n; i++) {
			int j = i;
			ll temp = a[i];
			while (j < n && temp + a[j + 1] <= x) temp += a[++j];
			i = j + 1;
			if (i <= n) rest += a[i];
		}
		
		return rest <= x;
	};
	
	ll l = lb, r = ub, res = ub;
	while (l <= r) {
		ll mid = (l + r) >> 1;
		if (check(mid)) r = (res = mid) - 1;
		else l = mid + 1;
	}
	
	cout << res << '\n';
}

signed main() {
	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	int T;
	cin >> T;
	while (T--)
	solve();
	return 0;
}

F. Caterpillar on a Tree

snow的代码

#include <bits/stdc++.h>
#define int long long 
using namespace std;

const int N = 2e5 + 10;

vector<int> G[N], tmp;
int dep[N], mx[N], f[N][20];

void dfs1(int u, int rt) {
	dep[u] = dep[rt] + 1;
	
	if (G[u].empty()) mx[u] = dep[u];
	
	f[u][0] = rt;
	for (int i = 1; i < 20; i++) {
		f[u][i] = f[f[u][i - 1]][i - 1];
	}
	
	for (int v : G[u]) {
		dfs1(v, u);
		mx[u] = max(mx[u], mx[v]);
	}
}

void dfs2(int u) {
	if (G[u].empty()) tmp.push_back(u);
	
	sort(G[u].begin(), G[u].end(), [&](int A, int B) {
		return mx[A] < mx[B];
	});
	
	for (int v : G[u]) {
		dfs2(v);
	}
}

int lca(int u, int v) {
	if (dep[u] < dep[v]) swap(u, v);
	
	for (int i = 19; i >= 0; i--) {
		if (dep[f[u][i]] >= dep[v]) u = f[u][i];
	}
	
	if (u == v) return u;
	
	for (int i = 19; i >= 0; i--) {
		if (f[u][i] != f[v][i]) {
			u = f[u][i], v = f[v][i];
		}
	}
	
	return f[u][0];
}

int get(int u, int v) {
	return dep[u] + dep[v] - dep[lca(u, v)] * 2;
}

void solve() {
	int n, k;
	cin >> n >> k;
	
	for (int i = 2; i <= n; i++) {
		int p; cin >> p;
		G[p].push_back(i);
	}
	
	dfs1(1, 0);
	dfs2(1);
	
	vector<int> vec;
	
	int ans = dep[tmp[0]] - 1;
	
	for (int i = 0; i + 1 < tmp.size(); i++) {
		
		int dis = get(tmp[i], tmp[i + 1]);
		ans += dis;
		
		if (dis > dep[tmp[i + 1]] - 1) {
			vec.push_back((dep[tmp[i + 1]] - 1) - dis);
		}
	}
	
	sort(vec.begin(), vec.end());
	
	for (int i = 0; i < k && i < vec.size(); i++) {
		ans += vec[i];
	}
	
	cout << ans;
}

signed main() {
	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	solve();
	return 0;
}
  • 17
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值