AtCoder Beginner Contest 185

AtCoder Beginner Contest 185

A - ABC Preparation

Solution

输出最小值

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

int main()
{
    int a1, a2, a3, a4;
    cin >> a1 >> a2 >> a3 >> a4;
    cout << min(min(a1, a2), min(a3, a4)) << endl;
    return 0;
}
B - Smartphone Addiction

Solution

模拟即可

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

int main()
{
    int n, t, m, cap;
    cin >> n >> m >> t; cap = n;
    bool fl= true, wh = true;
    int lt = 0;
    for(int i = 0; i < m * 2; ++i) {
        int mt; cin >> mt;
        if(wh) {
            n -= mt - lt;
        }
        else {
            n += mt - lt;
        }
        n = min(n, cap);
        if(n <= 0) fl = false;
        wh = !wh;
        lt = mt;
    }
    if(wh) {
        n -= t - lt;
    }
    else {
        n += t - lt;
    }
    n = min(n, cap);
    if(n <= 0) fl = false;
    cout << (fl ? "Yes" : "No") << endl;
    return 0;
}
C - Duodecim Ferra

Solution

裁成12段,需要11个裁点,长为L裁点有L-1个,所以答案为\(C_{L-1}^{11}\),因为中间结果会long long,所以用递推式计算:\(C_n^m=C_{n-1}^m+C_{n-1}^{m-1}\)

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

typedef long long ll;

ll c[222][222];

int main()
{
    ll l;
    cin >> l;
    l--;
    for(int i = 0; i <= l; ++i) c[i][0] = c[i][i] = 1, c[i][1] = i;
    for(int i = 1; i <= l; ++i) {
        for(int j = 2; j < i; ++j) {
            c[i][j] = c[i - 1][j - 1] + c[i - 1][j];
        }
    }
    cout << c[l][11] << endl;
    return 0;
}
D - Stamp

Solution

找到最小的白色区间,即为最大可用stamp width,然后对每段计算需要几个stamp求和即可。

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

const int maxn = 211111;

int a[maxn];

int main()
{
    int n, m; cin >> n >> m;
    vector<int> dis;
    a[0] = 1;
    for(int i = 1; i <= m; ++i) {
        cin >> a[i];
    }
    a[m + 1] = n;
    sort(a, a + m + 2);
    int v = n;
    for(int i = 2; i < m + 1; ++i) {
        if(a[i] - a[i - 1] - 1 > 0) {
            dis.push_back(a[i] - a[i - 1] - 1);
            v = min(v, a[i] - a[i - 1] - 1);
        }
    }
    if(m >= 1 && a[1] - a[0] > 0) {
        dis.push_back(a[1] - a[0]);
        v = min(v, a[1] - a[0]);
    }
    if(m >= 1 && n - a[m] > 0) {
        dis.push_back(n - a[m]);
        v = min(v, n - a[m]);
    }
    int ans = 0;
    if(m == 0) ans = 1;
    if(dis.size()) {
        for(auto d : dis) {
            ans += d / v;
            if(d % v) ans++;
        }
    }
    cout << ans << endl;
    return 0;
}
E - Sequence Matching

Solution

直接套最小编辑距离的板子

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

const int INF = 0x3f3f3f3f;

int dp[1005][1005];     /*dp[i][j]表示表示A串从第0个字符开始到第i个字符和B串从第0个字符开始到第j个字符,这两个字串的编辑距离。字符串的下标从1开始。*/
int a[1005],b[1005];   //a,b字符串从下标1开始
int n, m;

int EditDis()
{
    int len1 = n;
    int len2 = m;
    //初始化
    for(int i=1;i<=len1;i++)
        for(int j=1;j<=len2;j++)
            dp[i][j] = INF;
    for(int i=1;i<=len1;i++)
        dp[i][0] = i;
    for(int j=1;j<=len2;j++)
        dp[0][j] = j;
    for(int i=1;i<=len1;i++)
    {
        for(int j=1;j<=len2;j++)
        {
            int flag;
            if(a[i]==b[j])
                flag=0;
            else
                flag=1;
            dp[i][j]=min(dp[i-1][j]+1,min(dp[i][j-1]+1,dp[i-1][j-1]+flag));
            //dp[i-1][j]+1表示删掉字符串a最后一个字符a[i]
            //dp[i][j-1]+1表示给字符串添加b最后一个字符
            //dp[i-1][j-1]+flag表示改变,相同则不需操作次数,不同则需要,用flag记录
        }
    }
    return dp[len1][len2];
}

int main()
{
    cin >> n >> m;
    for(int i = 1; i <= n; ++i) cin >> a[i];
    for(int j = 1; j <= m; ++j) cin >> b[j];
    cout << EditDis() << endl;
    return 0;
}
F - Range Xor Query

Solution

线段树裸题,由于处理的是异或运算,所以树状数组同样可以求解,亲测效率更高。

线段树版本:

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

typedef long long ll;

const int maxn = 1111111;

ll tree[maxn], n, q, arr[maxn];

void build(int ad, int l, int r)
{
    if(l == r) {
        tree[ad] = arr[l];
        return;
    }
    int mid = (l + r) >> 1;
    build(ad << 1, l, mid);
    build(ad << 1 | 1, mid + 1, r);
    tree[ad] = tree[ad << 1] ^ tree[ad << 1 | 1];
    return;
}

void change(int ad, int l, int r, int d, ll ch)
{
    if(l == r) {
        if(l == d) {
            tree[ad] = tree[ad] ^ ch;
        }
        return;
    }
    int mid = (l + r) >> 1;
    if(mid >= d) {
        change(ad << 1, l, mid, d, ch);
    }
    else {
        change(ad << 1 | 1, mid + 1, r, d, ch);
    }
    tree[ad] = tree[ad << 1] ^ tree[ad << 1 | 1];
    return;
}

ll query(int ad, int l, int r, int ql, int qr)
{
    if(r < ql || l > qr) return 0;
    if(l >= ql && r <= qr) return tree[ad];
    int mid = (l + r) >> 1;
    ll ans = 0;
    if(mid >= ql) {
        ans = ans ^ query(ad << 1, l, mid, ql, qr);
    }
    if(mid < qr) {
        ans = ans ^ query(ad << 1 | 1, mid + 1, r, ql, qr);
    }
    return ans;
}

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cin >> n >> q;
    for(int i = 1; i <= n; ++i) cin >> arr[i];
    build(1, 1, n);
    while(q--) {
        ll t, x, y;
        cin >> t >> x >> y;
        if(t == 1) {
            change(1, 1, n, x, y);
        }
        else {
            cout << query(1, 1, n, x, y) << endl;
        }
    }
    return 0;
}

树状数组版本:

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

inline int lowbit(int x) { return (x & (-x)); }

typedef long long ll;

const int maxn = 1111111;

ll tree[maxn], arr[maxn], n, q;

void update(int ad, ll x) {
    while(ad <= n) {
        tree[ad] = tree[ad] ^ x;
        ad += lowbit(ad);
    }
    return;
}

ll query(int ad) {
    ll ans = 0;
    while(ad) {
        ans ^= tree[ad];
        ad -= lowbit(ad);
    }
    return ans;
}

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cin >> n >> q;
    for(int i = 1; i <= n; ++i) {
        cin >> arr[i];
        update(i, arr[i]);
    }
    while(q--) {
        ll t, x, y;
        cin >> t >> x >> y;
        if(t == 1) {
            update(x, y);
        }
        else {
            cout << (query(y) ^ query(x - 1)) << endl;
        }
    }
    return 0;
}

对于两种方式都可以的题,更喜欢用树状数组写,毕竟码量少,不容易出错==。

posted @ 2020-12-14 11:27  落水清心  阅读(207)  评论(0编辑  收藏  举报