第十四次CCF计算机软件能力认证

1、卖菜

ACwing 3262

#include <iostream>
#include <algorithm>
using namespace std;

const int N = 1010;

int n, a[N];

int main() {
    cin >> n;
    for (int i = 1; i <= n; i++) cin >> a[i];
    for (int i = 1; i <= n; i++) {
        int cnt = 0, sum = 0;
        if (a[i - 1]) cnt++, sum += a[i - 1];
        if (a[i]) cnt++, sum += a[i];
        if (a[i + 1]) cnt++, sum += a[i + 1];
        cout << sum / cnt << " ";
    }
    return 0;
}

2、买菜

ACwing 3263

#include <iostream>
#include <algorithm>
using namespace std;

#define x first
#define y second

typedef pair<int, int> PII;
const int N = 2010;

int n;
PII p[N], q[N];

int get(PII a, PII b) {
    if (a.y < b.x || b.y < a.x) return 0;
    return min(a.y, b.y) - max(a.x, b.x);
}

int main() {
    cin >> n;
    for (int i = 0; i < n; i++) cin >> p[i].x >> p[i].y;
    for (int i = 0; i < n; i++) cin >> q[i].x >> q[i].y;
    int res = 0;
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            res += get(p[i], q[j]);
    cout << res << endl;
    return 0;
} 

3、元素选择器

ACwing 3264

4、再卖菜(差分约束)

ACwing 3265

假设存在两个序列 a 1 , a 2 , ⋯   , a n a_1,a_2, \cdots, a_n a1,a2,,an b 1 , b 2 , ⋯   , b n b_1, b_2, \cdots, b_n b1,b2,,bn

先考虑 b b b 序列中的一般情况,即 b i = a i − 1 + a i + a i + 1 3   ( i ∈ [ 2 , n − 1 ] ) b_i = \frac{a_{i-1} + a_i + a_{i + 1}}{3}\ (i\in[2,n-1]) bi=3ai1+ai+ai+1 (i[2,n1]) 的时候 ,这里之前可以预处理处序列 a a a 的前缀和 S S S 以方便求值,那么 b i = ⌊ S i + 1 − S i − 2 3 ⌋ b_i = \left \lfloor \frac{S_{i+1} - S_{i-2}}{3} \right \rfloor bi=3Si+1Si2 ,那么就存在关系: 3 b i ≤ S i + 1 − S i − 2 ≤ 3 b i + 2 3b_i \le S_{i+1} - S_{i-2} \le 3b_i + 2 3biSi+1Si23bi+2又根据题目可知 a i ≥ 1 a_i \ge 1 ai1,因此还存在条件 S i − S i − 1 ≥ 1 S_i - S_{i-1} \ge 1 SiSi11

综上:题目转换为在满足条件 { 3 b i ≤ S i + 1 − S i − 2 ≤ 3 b i + 2 S i − S i − 1 ≥ 1 \begin{cases} &3b_i \le S_{i+1} - S_{i-2} \le 3b_i + 2\\ &S_i - S{i-1} \ge 1\\ \end{cases} {3biSi+1Si23bi+2SiSi11的前提下求出 S i ( i ∈ [ 1 , n ] ) S_i(i\in[1, n]) Si(i[1,n])的值。

因为求解最小值,所以应该求解最长路,其差分格式对应于 d b ≥ d a + c d_b \ge d_a + c dbda+c,表示一条从 a a a 指向 b b b 且权值为 c c c 的边。

将所有的不等式转化成差分的格式:
{ S i + 1 ≥ S i − 2 + 3 b i S i − 2 ≥ S i + 1 − ( 3 b i + 2 ) S i ≥ S i − 1 + 1 \begin{cases} &S_{i+1} \ge S_{i-2} + 3b_i\\ &S_{i-2} \ge S_{i+1} - (3b_i + 2)\\ &S_i \ge S_{i-1} + 1\\ \end{cases} Si+1Si2+3biSi2Si+1(3bi+2)SiSi1+1注意这个题目存在一个绝对值 S 0 = 0 S_0 = 0 S0=0

因为差分约束可以求出每个元素的最小值,那么也就相当于求解出了字典序的最小值。

#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;

const int N = 310, M = N * 3; // 有三个不等式,要建三条边

int n;
int h[N], e[M], w[M], ne[M], idx;
int dist[N], q[N];
int b[N];
bool st[N];

void add(int a, int b, int c) {
    e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
}

void spfa() {
    int hh = 0, tt = 1;
    memset(dist, -0x3f, sizeof dist);
    dist[0] = 0;
    q[0] = 0;
    while (hh != tt) {
        int t = q[hh++];
        if (hh == N) hh = 0;
        st[t] = false;
        for (int i = h[t]; ~i; i = ne[i]) {
            int j = e[i];
            if (dist[j] < dist[t] + w[i]) {
                dist[j] = dist[t] + w[i];
                if (!st[j]) {
                    q[tt++] = j;
                    if (tt == N) tt = 0;
                    st[j] = true;
                }
            }
        }
    }
}

int main() {
    cin >> n;
    memset(h, -1, sizeof h);
    for (int i = 1; i <= n; i++) cin >> b[i];
    for (int i = 2; i < n; i++) {
        add(i - 2, i + 1, b[i] * 3);
        add(i + 1, i - 2, -(b[i] * 3 + 2));
    }
    add(0, 2, b[1] * 2), add(2, 0, -(b[1] * 2 + 1)); // 边上两个点
    add(n - 2, n, b[n] * 2), add(n, n - 2, -(b[n] * 2 + 1));
    for (int i = 1; i <= n; i++) add(i - 1, i, 1);
    spfa();
    for (int i = 1; i <= n; i++) cout << dist[i] - dist[i - 1] << ' '; // dist[i] 对应于 S[i]
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值