小记_Codeforces Round 922 (Div. 2)

A-Brick Wall

这道题的难点在于题意,如果光看题面不看样例和解释很难看懂。
题意为,给定一个 n ∗ m n * m nm 的矩形面积,让你用 1 ∗ k ( 2 ≤ k ) 1 * k (2 \leq k) 1k(2k) 的方块去填充(不能旋转),问你最多可以填入多少块。
所以解就是 n ∗ ⌊ x / 2 ⌋ n * \lfloor x / 2 \rfloor nx/2

B-Minimize Inversions

给定两个长度为 n n n 的全排列,你可以进行以下操作任意次:
a i a_i ai a j a_j aj交换的同时,交换 b i b_i bi b j b_j bj
问使得“两个全排列的逆序对个数之和最小”的排列是什么。
解决这个问题需要从个例的关系去推整体。
比如两个全排列为:
1 , 2 1, 2 1,2
2 , 1 2, 1 2,1
无论怎么交换,都会有1个逆序对。
再看下面的情况:
2 , 1 2, 1 2,1
2 , 1 2, 1 2,1
如果交换 a 1 a_1 a1 a 2 a_2 a2 b 1 b_1 b1 b 2 b_2 b2,逆序对的数量则会从 2 2 2 个变为 0 0 0 个。
将上面两种情况推至整体,可以知道只有在 a i > a j a_i > a_j ai>aj 同时 b i > b j b_i > b_j bi>bj 时进行交换才会使得逆序对数量减少。
那么最简单的方法就是将其中一个数组从小到大排列即可。

#include <bits/stdc++.h>
using namespace std;
const int N = 2e6 + 10;
int n, m;
int a[N];
int ans[N], b;

void solve() {
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
    }
    for (int i = 1; i <= n; i++) {
        cin >> b;
        ans[a[i]] = b;
    }
    for (int i = 1; i <= n; i++)
        cout << i << ' ';
    cout << '\n';
    for (int i = 1; i <= n; i++)
        cout << ans[i] << ' ';
    cout << '\n';
    return;
}

int main() {
    int T = 1;
    cin >> T;
    while (T--) {
        solve();
    }
    return 0;
}

C-XOR-distance

给定 a , b , r a, b, r a,b,r,求 ∣ ( a ⊕ x ) − ( b ⊕ x ) ∣ \left| (a \oplus x) -(b \oplus x)\right| (ax)(bx) 的最小值, 1 ≤ x ≤ r 1 \leq x \leq r 1xr
按位来看、并且先不看绝对值:如果 a a a b b b 相等,那么 x x x 无论取什么值都无法对结果造成影响,反之,可以通过 x x x 的取 1 1 1 或是 0 0 0 来影响正负。
解,从最高的不同的位看起,我们让那一位是 1 1 1 的那个数为大的数,另一个数为小的数。让这一位的 x x x 0 0 0,如果为 1 1 1 会使得 x x x 更大,在后续的影响中不如填 0 0 0 优。接着后续的低位 a , b a, b a,b 如果出现 0 , 1 0, 1 0,1 不同的情况,如果小的那个数为 1 1 1 则不用处理;否则,需要让 x x x 的那一位为 1 1 1 ,让其变为 1 1 1 ,注意处理 x x x 不够大的情况。
我代码写得丑,可以用数组来代替 n , m n, m n,m

#include <bits/stdc++.h>
using namespace std;
const int N = 2e6 + 10;
long long n, m, r;

void solve() {
    cin >> n >> m >> r;
    long long res = 0, now = 0;
    int t = -1, idx = 0;
    for (int i = 63; i >= 0; i--) {
        if ((n >> i & 1) != (m >> i & 1)) {
            t = i;
            if (n >> i & 1) idx = 2;
            else idx = 1;
            break;
        }
    }
    if (t == -1) cout << 0 << '\n';
    else {
        res += 1ll << t;
        for (int i = t - 1; i >= 0; i--) 
        if ((n >> i & 1) != (m >> i & 1)){
            if (idx == 1) {
                if (!(n >> i & 1)) {
                    if (now + (1ll << i) <= r) {now += (1ll << i); res -= (1ll << i);}
                    else res += (1ll << i);
                } else res -= (1ll << i);
            } else {
                if (!(m >> i & 1)) {
                    if (now + (1ll << i) <= r) {now += (1ll << i); res -= (1ll << i);}
                    else res += (1ll << i);
                } else res -= (1ll << i);
            }
        }cout << res << '\n';
    }
    
    return;
}

int main() {
    int T = 1;
    cin >> T;
    while (T--) {
        solve();
    }
    return 0;
}

D-Blocking Elements

给定一个 n n n 个数的序列 a a a,让你从中选出 m m m (m个数任意)个数,这会将其他的数分隔开,成为一个个区间,要使得: m a x ( m 个数的和,所有区间和的最大值) max(m个数的和,所有区间和的最大值) max(m个数的和,所有区间和的最大值)最小
a i ≤ 1 0 9 a_i \leq 10^9 ai109
解:最大值最小化,似乎可以用二分做。
最主要的是check函数如何写,如果贪心地,区间和大于某个数就划开,会有问题,会发现此时的划分不一定是最优的,这点从样例case2可以看出。
那么我们就需要设计以第 i i i 个数作为最后一个划分点的状态转移,每次枚举以 i i i 前面的某个点作为上一个划分点,用 d p [ i ] dp[i] dp[i]来表示以 i i i点作为最后一个划分点的所有作为划分的数的和的最小值。
看起来是 O ( n 2 ) O(n^2) O(n2) 的转移,但由于具有单调性,能优化到 O ( n ) O(n) O(n)

#include <bits/stdc++.h>
using namespace std;
const int N = 2e6 + 10;
int n, m;
long long a[N], s[N], sum;
long long dp[N];
long long q[N], hh, tt;
bool check(long long mid) {
    hh = 0, tt = -1;
    q[++tt] = 0;
    for (int i = 1; i <= n; i++) {
        while (tt - hh >= 0 && s[i-1] - s[q[hh]] > mid) hh++;
        dp[i] = dp[q[hh]] + a[i];
        while (tt - hh >= 0 && dp[q[tt]] >= dp[i]) tt--;
        q[++tt] = i;
    }
    for (int i = 1; i <= n; i++)
        if (dp[i] <= mid && sum - s[i] <= mid) return true;
    return false;
}
void solve() {
    sum = 0;
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
        s[i] = s[i-1] + a[i];
        sum += a[i];
    }
    long long l = 1, r = sum;
    while (l < r) {
        long long mid = l + r >> 1;
        if (check(mid)) r = mid;
        else l = mid + 1;
    }
    cout << l << '\n';
    return;
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    int T = 1;
    cin >> T;
    while (T--) {
        solve();
    }
    return 0;
}
  • 23
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
抱歉,根据提供的引用内容,我无法理解你具体想要问什么问题。请提供更清晰明确的问题,我将竭诚为你解答。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Codeforces Round 860 (Div. 2)题解](https://blog.csdn.net/qq_60653991/article/details/129802687)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [【Codeforces】 Codeforces Round 865 (Div. 2) (补赛)](https://blog.csdn.net/t_mod/article/details/130104033)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [Codeforces Round 872 (Div. 2)(前三道](https://blog.csdn.net/qq_68286180/article/details/130570952)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值