AtCoder Beginner Contest 366 A~F

A.Election 2(思维)

题意:

AtCoderAtCoderAtCoder 市正在举行市长选举。候选人是高桥和青木。
NNN 张有效选票投给两位候选人中的任何一位,目前正在进行计票。这里, NNN 是奇数。
目前的计票结果是:高桥 TTT 票,青木 AAA 票。
请判断此时选举结果是否已经确定。

分析:

我们计算票数少的加上剩下的所有票能不能超过票数多的即可。

代码:

#include <bits/stdc++.h>

using namespace std;

int main() {
    int a, b, c;
    cin >> a >> b >> c;
    if (min(b, c) + a - b - c > max(b, c))
        cout << "No" << endl;
    else
        cout << "Yes" << endl;
    return 0;
}

B. Vertical Writing(模拟)

题意:

给你一个横向书写的文本。将其转换为竖写,用 * 填充空格。

给你 NNN 个由小写英文字母组成的字符串 S1,S2,…,SNS_1, S_2, \dots, S_NS1,S2,,SN 。设 MMM 为这些字符串的最大长度。

打印 MMM 个满足以下条件的字符串 T1,T2,…,TMT_1, T_2, \dots, T_MT1,T2,,TM

  • 每个 TiT_iTi 由小写英文字母和 * 组成。
  • 每个 TiT_iTi 不以 * 结尾。
  • 每个 1≤i≤N1 \leq i \leq N1iN 都满足以下条件:
    • 对于每个 1≤j≤∣Si∣1 \leq j \leq |S_i|1jSiTjT_jTj(N−i+1)(N-i+1)(Ni+1) 个字符存在, T1,T2,…,T∣Si∣T_1, T_2, \dots, T_{|S_i|}T1,T2,,TSi(N−i+1)(N-i+1)(Ni+1) 个字符按此顺序连接等于 SiS_iSi
    • 对于每一个 ∣Si∣+1≤j≤M|S_i| + 1 \leq j \leq MSi+1jMTjT_jTj(N−i+1)(N-i+1)(Ni+1) 个字符要么不存在,要么是 *

这里, ∣Si∣|S_i|Si 表示字符串 SiS_iSi 的长度。

分析:

我们将nnn个字符串顺时针旋转909090度,然后对于每一行,从右往左,一旦碰到字符,后续再碰到 时,替换成*即可。

代码:

#include <bits/stdc++.h>

using namespace std;
char tmp[105][105];

int main() {
    int n, m = -1;
    cin >> n;
    for (int i = 0; i < n; i++) {
        string s;
        int l;
        cin >> s;
        l = s.length();
        m = max(m, l);
        for (int j = 0; j < l; j++)
            tmp[i][j] = s[j];
    }
    for (int i = 0; i < m; i++) {
        string s = "";
        for (int j = n - 1; j >= 0; j--) {
            if (tmp[j][i])
                s += tmp[j][i];
            else
                s += '*';
        }
        while (s[s.length() - 1] == '*')
            s = s.substr(0, s.length() - 1);
        cout << s << endl;
    }
    return 0;
}

C.Balls and Bag Query(数据结构)

题意:

你有一个空袋子。给你 QQQ 个查询,必须按顺序处理。

有三种查询。

  • 1 x :将一个写有整数 xxx 的球放入袋子中。
  • 2 x : 从袋子中取出一个写有整数 xxx 的球并丢弃。当给出这个查询时,可以保证袋子中有一个写着整数 xxx 的球。
  • 3 : 打印袋中写有不同整数的球的个数。

分析:

mapmapmap维护一下各个数字球的个数,当map[x]=0map[x]=0map[x]=0时移除该元素,询问就是map.size()map.size()map.size()

代码:

#include <bits/stdc++.h>

using namespace std;

int main() {
    int q;
    cin >> q;
    map<int, int> tmp;
    while (q--) {
        int op;
        cin >> op;
        if (op == 1) {
            int x;
            cin >> x;
            tmp[x]++;
        } else if (op == 2) {
            int x;
            cin >> x;
            tmp[x]--;
            if (tmp[x] == 0)
                tmp.erase(x);
        } else {
            cout << tmp.size() << endl;
        }
    }
    return 0;
}

D.Cuboid Sum Query (思维)

题意:

给你一个正整数 NNN 和一个整数 Ax,y,zA_{x,y,z}Ax,y,z ,每个整数 (x,y,z)(x, y, z)(x,y,z) 的三元组都是 1≤x,y,z≤N1 \leq x, y, z \leq N1x,y,zN

你将得到以下格式的 QQQ 个查询,必须按顺序处理。

对于 iii 查询 (1≤i≤Q)(1 \leq i \leq Q)(1iQ) ,我们会给你一个由整数 (Lxi,Rxi,Lyi,Ryi,Lzi,Rzi)(Lx_i, Rx_i, Ly_i, Ry_i, Lz_i, Rz_i)(Lxi,Rxi,Lyi,Ryi,Lzi,Rzi) 组成的元组 1≤Lxi≤Rxi≤N1 \leq Lx_i \leq Rx_i \leq N1LxiRxiN1≤Lyi≤Ryi≤N1 \leq Ly_i \leq Ry_i \leq N1LyiRyiN1≤Lzi≤Rzi≤N1 \leq Lz_i \leq Rz_i \leq N1LziRziN 。查找:

∑x=LxiRxi∑y=LyiRyi∑z=LziRziAx,y,z\displaystyle{\sum_{x=Lx_i}^{Rx_i} \sum_{y=Ly_i}^{Ry_i} \sum_{z=Lz_i}^{Rz_i} A_{x,y,z}}x=LxiRxiy=LyiRyiz=LziRziAx,y,z .

分析:

我们令Si,j,k=∑x=1i−1∑y=1j−1∑z=1k−1Ax,y,zS_{i,j,k}=\sum\limits_{x=1}^{i-1} \sum\limits_{y=1}^{j-1}\sum\limits_{z=1}^{k-1}A_{x,y,z}Si,j,k=x=1i1y=1j1z=1k1Ax,y,z1≤i,j,k≤N+11 \leq i,j,k \leq N+11i,j,kN+1 。(如果 iiijjjkkk000 ,我们定义为 Si,k,k=0S_{i,k,k}=0Si,k,k=0 )。

那么 ∑x=LxiRxi∑y=LyiRyi∑z=LziRziAx,y,z=SRxi+1,Ryi+1,Rzi+1−SLxi,Rxi+1,Rzi+1−SRxi+1,Lyi,Rzi+1−SRxi+1,Ryi+1,Lzi+SLxi,Lyi,Rzi+1+SLxi,Ryi+1,Lzi+SRxi+1,Lyi,Lzi−SLxi,Lyi,Lzi\sum\limits_{x=Lx_i}^{Rx_i} \sum\limits_{y=Ly_i}^{Ry_i} \sum\limits_{z=Lz_i}^{Rz_i} A_{x,y,z}=S_{Rx_i+1,Ry_i+1,Rz_i+1}-S_{Lx_i,Rx_i+1,Rz_i+1}-S_{Rx_i+1,Ly_i,Rz_i+1}-S_{Rx_i+1,Ry_i+1,Lz_i}+S_{Lx_i,Ly_i,Rz_i+1}+S_{Lx_i,Ry_i+1,Lz_i}+S_{Rx_i+1,Ly_i,Lz_i}-S_{Lx_i,Ly_i,Lz_i}x=LxiRxiy=LyiRyiz=LziRziAx,y,z=SRxi+1,Ryi+1,Rzi+1SLxi,Rxi+1,Rzi+1SRxi+1,Lyi,Rzi+1SRxi+1,Ryi+1,Lzi+SLxi,Lyi,Rzi+1+SLxi,Ryi+1,Lzi+SRxi+1,Lyi,LziSLxi,Lyi,Lzi 成立。

所以,如果我们能快速计算 SSS ,那么每个查询都能在恒定的时间内得到回答。

事实上,根据 Si,j,k=Si−1,j,k+Si,j−1,k+Si,j,k−1−Si−1,j−1,k−Si−1,j,k−1−Si,j−1,k−1+Si−1,j−1,k−1+Ai−1,j−1,k−1S_{i,j,k}=S_{i-1,j,k}+S_{i,j-1,k}+S_{i,j,k-1}-S_{i-1,j-1,k}-S_{i-1,j,k-1}-S_{i,j-1,k-1}+S_{i-1,j-1,k-1}+A_{i-1,j-1,k-1}Si,j,k=Si1,j,k+Si,j1,k+Si,j,k1Si1,j1,kSi1,j,k1Si,j1,k1+Si1,j1,k1+Ai1,j1,k1 的性质, SSS 可以快速计算。

代码:

#include <bits/stdc++.h>

using namespace std;
typedef long long LL;
LL a[105][105][105];
LL sum[105][105][105];

int main() {
    int n;
    cin >> n;
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            for (int k = 0; k < n; ++k) {
                cin >> a[i][j][k];
            }
        }
    }
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            for (int k = 0; k < n; ++k) {
                sum[i + 1][j + 1][k + 1] =
                        sum[i][j + 1][k + 1] + sum[i + 1][j][k + 1] +
                        sum[i + 1][j + 1][k] - sum[i][j][k + 1] - sum[i][j + 1][k] -
                        sum[i + 1][j][k] + sum[i][j][k] + a[i][j][k];
            }
        }
    }
    int q;
    cin >> q;
    for (int i = 0; i < q; ++i) {
        int lx, rx, ly, ry, lz, rz;
        cin >> lx >> rx >> ly >> ry >> lz >> rz;
        lx--, ly--, lz--;
        LL ans = sum[rx][ry][rz] - sum[lx][ry][rz] - sum[rx][ly][rz] -
                 sum[rx][ry][lz] + sum[lx][ly][rz] + sum[lx][ry][lz] +
                 sum[rx][ly][lz] - sum[lx][ly][lz];
        cout << ans << endl;
    }
    return 0;
}

E.Manhattan Multifocal Ellipse (双指针)

题意:

给你一个二维平面上的 NNN(x1,y1),(x2,y2),…,(xN,yN)(x_1, y_1), (x_2, y_2), \dots, (x_N, y_N)(x1,y1),(x2,y2),,(xN,yN) 和一个非负整数 DDD

∑i=1N(∣x−xi∣+∣y−yi∣)≤D\displaystyle \sum_{i=1}^N (|x-x_i|+|y-y_i|) \leq Di=1N(xxi+yyi)D 的整数对 (x,y)(x, y)(x,y) 的个数。

分析:

观察xi,yix_i,y_ixi,yi的范围,可知x,yx,yx,y的取值范围是[−2×106,2×106][-2 \times 10^6,2 \times 10^6][2×106,2×106] 。将x,yx,yx,y分开来计算,枚举所有的xxx,计算$ (|x-x \times i|) $的和(可以通过正反方向预处理前缀和来计算),对 yyy 同理。然后对于所有的 x,yx,yx,y,从两端开始双指针枚举和≤D\le DD的情况。

代码:

#include <bits/stdc++.h>

using namespace std;
typedef long long LL;
const int N = 3e5 + 10;
LL x[N], y[N], a[N], b[N], t[1000005], ans;

int main() {
    int n, d;
    cin >> n >> d;
    for (int i = 1; i <= n; i++) {
        cin >> x[i] >> y[i];
    }
    sort(x + 1, x + n + 1);
    sort(y + 1, y + n + 1);
    x[n + 1] = LONG_LONG_MAX;
    y[n + 1] = LONG_LONG_MAX;
    for (int i = 1; i <= n; i++) {
        a[i] = a[i - 1] + x[i];
        b[i] = b[i - 1] + y[i];
    }
    for (int i = -2e6; i <= 2e6; i++) {
        LL tmp = upper_bound(x + 1, x + n + 2, i) - x;
        LL id = i * (tmp - 1) - a[tmp - 1] + a[n] - a[tmp - 1] - i * (n - tmp + 1);
        if (id <= d) {
            t[id]++;
        }
    }
    for (int i = 1; i <= d; i++) {
        t[i] += t[i - 1];
    }
    for (int i = -2e6; i <= 2e6; i++) {
        LL tmp = upper_bound(y + 1, y + n + 2, i) - y;
        LL id = i * (tmp - 1) - b[tmp - 1] + b[n] - b[tmp - 1] - i * (n - tmp + 1);
        if (id <= d) {
            ans += t[d - id];
        }
    }
    cout << ans << endl;
    return 0;
}

F.Maximum Composition (dp)

题意:

给你 NNN 个线性函数 f1,f2,…,fNf_1, f_2, \ldots, f_Nf1,f2,,fN ,其中 fi(x)=Aix+Bif_i(x) = A_i x + B_ifi(x)=Aix+Bi .

求由 KKK 组成的序列 p=(p1,p2,…,pK)p = (p_1, p_2, \ldots, p_K)p=(p1,p2,,pK)fp1(fp2(…fpK(1)…))f_{p_1}(f_{p_2}(\ldots f_{p_K}(1) \ldots ))fp1(fp2(fpK(1))) 的最大可能值。介于 111NNN (含)之间的个不同整数的最大可能值 fp1(fp2(…fpK(1)…))f_{p_1}(f_{p_2}(\ldots f_{p_K}(1) \ldots ))fp1(fp2(fpK(1)))

分析:

我们首先思考当用于序列 pppKKK 整数固定不变时, ppp 具有什么样的性质?
可以发现:
fi(fj(x))f_i(f_j(x))fi(fj(x))fj(fi(x))f_j(f_i(x))fj(fi(x)) 的排序与 xxx 无关,完全取决于 Ai−1Bi\frac{A_i-1}{B_i}BiAi1Aj−1Bj\frac{A_j-1}{B_j}BjAj1 的排序。如果是 Ai−1Bi\frac{A_i-1}{B_i}BiAi1>>> Aj−1Bj\frac{A_j-1}{B_j}BjAj1 ,那么就是 fi(fj(x))>fj(fi(x))f_i(f_j(x))>f_j(f_i(x))fi(fj(x))>fj(fi(x))

根据这一性质,在给定 KKK 个整数用于 ppp 时,当 ppp 满足 Ap1−1Bp1≥Ap2−1Bp2≥…≥ApK−1BpK\frac{A_{p_1}-1}{B_{p_1}} \geq \frac{A_{p_2}-1}{B_{p_2}} \geq \ldots \geq \frac{A_{p_K}-1}{B_{p_K}}Bp1Ap11Bp2Ap21BpKApK1 时,值 fp1(fp2(…fpK(1)…))f_{p_1}(f_{p_2}(\ldots f_{p_K}(1) \ldots))fp1(fp2(fpK(1))) 取最大值。

为简单起见,假设对 (A,B)(A,B)(A,B) 进行排序,使 A1−1B1≥A2−1B2≥…AN−1BN\frac{A_1-1}{B_1} \geq \frac{A_2-1}{B_2} \geq \ldots \frac{A_N-1}{B_N}B1A11B2A21BNAN1 .

那么问题可以改写如下:

求介于 111NNN 之间的整数序列 ppp 的最大值 fp1(fp2(…fpK(1)…))f_{p_1}(f_{p_2}(\ldots f_{p_K}(1) \ldots))fp1(fp2(fpK(1))) ,使得 p1<p2<…<pNp_1 < p_2 < \ldots < p_Np1<p2<<pN
我们可以用dpdpdp来解决这问题。
当决定 pK,pK−1,…pK−ip_K,p_{K-1},\ldots p_{K-i}pK,pK1,pKi 时,求 fpK−i(…fpK(1)…)f_{p_{K-i}}(\ldots f_{p_K}(1)\ldots)fpKi(fpK(1)) 的最大值 $dp_{i,j}=( $从而求得 pK−i≥j)p_{K-i} \geq j)pKij) .
我们定义dpi,j=max(dpi,j+1,Aj×dpi−1,j+1+Bj)dp_{i,j}=\text{max}(dp_{i,j+1},A_j \times dp_{i-1,j+1}+B_j)dpi,j=max(dpi,j+1,Aj×dpi1,j+1+Bj) ,所求答案为 dpK,1dp_{K,1}dpK,1

代码:

#include <bits/stdc++.h>

using namespace std;

int main() {
    int n, k;
    cin >> n >> k;
    vector<int> a(n), b(n);
    for (int i = 0; i < n; ++i) {
        cin >> a[i] >> b[i];
    }
    vector<int> num(n);
    for (int i = 0; i < n; ++i)
        num[i] = i;
    sort(num.begin(), num.end(), [&](int i, int j) { return b[i] * (a[j] - 1) > b[j] * (a[i] - 1); });
    vector<long long> dp(k + 1, -1e9);
    dp[0] = 1;
    for (auto i: num) {
        vector<long long> tmp = dp;
        for (int j = 0; j < k; ++j)
            if (dp[j] != -1e9) {
                tmp[j + 1] = max(tmp[j + 1], dp[j] * a[i] + b[i]);
            }
        dp = move(tmp);
    }
    cout << dp[k] << endl;
    return 0;
}

赛后交流

在比赛结束后,会在交流群中给出比赛题解,同学们可以在赛后查看题解进行补题。

群号: 704572101,赛后大家可以一起交流做题思路,分享做题技巧,欢迎大家的加入。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值