Codeforces Global Round 21

复健场,类似的粗心不该再犯!

传送门

A、NIT orz!

Des
Solution
没啥好说的,通过观察,找到最大ai | m即可
Code

void solve()
{
    cin >> n >> z;
    for(int i = 1; i <= n; ++i) cin >> a[i];
    int mx = 0;
    for(int i = 1; i <= n; ++i) mx = max(mx, a[i] | z);
    cout << mx << "\n";
}

B、NIT Destroys the Universe

Des
给你一个数组,每次选择一段区间[l, r],这段区间里面所有数变成该区间的MEX
Solution

真的很呆,被样例误解了,被坑了,原本以为以0为隔板,有多少段连续不是0,就是答案 ,事实是最多两次,整段的mex肯定相同,然后再来一次就可以变成0,其他情况特判就行了。

Code

void solve()
{
    cin >> n;
    for(int i = 1; i <= n; ++i)
    {
        cin >> a[i];
    }
    int ans = 0;
    for(int i = 1; i <= n; ++i)
    {
        if(a[i] != 0)
        {
            int j = i;
            while(a[j] != 0 && j <= n) ++j;
            ans++;
            i = j - 1;
        }
        if(ans >= 2) break;
    }
    cout << (ans <= 1 ? ans : 2) << "\n";
}

C、Fishingprince Plays With Array

Des
给你两个数组a, b和一个数字k,你可以对a进行操作。
1、让ai能整除k的数,变成k个ai / k
2、将k个相同连续的数字合成,替换到a数组中
问是否最后a数组能和b数组都相同。
Solution
直接暴力拆a,b的每一个数,直到最后不能再拆为之,最后看两个数组是否相同,这里如果k很小,会爆内存。我们设计一个pair,就是值的x的最小因子出现了多少次,每次合并pair,就不会MLE了,本人因为if自己粗心,一直wa。。。
Code

void solve()
{
    cin >> n >> k;
    int x;
    vector<pair<int, int> > v1;
    for(int i = 1; i <= n; ++i)
    {
        int cnt = 1;
        cin >> x;
        while(x % k == 0)
        {
            cnt *= k;
            x /= k;
        }
        if(v1.size())
        {
            auto& v = v1.back();
            if(v.second == x) v.first += cnt;
            else v1.push_back({cnt, x});
        }
        else v1.push_back({cnt, x});

    }
    cin >> m;
    vector<pair<int, int> > v2;
    for(int i = 1; i <= m; ++i)
    {
        int cnt = 1;
        cin >> x;
        while(x % k == 0)
        {
            cnt *= k;
            x /= k;
        }
        if(v2.size())
        {
            auto& v = v2.back();
            if(v.second == x) v.first += cnt;
            else v2.push_back({cnt, x});
        }
        else v2.push_back({cnt, x});

    }
    if(v1.size() != v2.size()) cout << "No\n";
    else
    {
        for(int i = 0; i < v1.size(); ++i)
        {
            if( v1[i].first != v2[i].first || v1[i].second != v2[i].second)
            {
                cout << "No\n";
                return;
            }
        }
        cout << "Yes\n";
    }
}

D、Permutation Graph

Des
给你一个1-n的任意排列组合,如果一个[l, r]区间,最小值是a[l], 最大值是a[r],则存在一个l->r的无向边。
Solution
建一颗能查询最大最小值的线段树,每次递归,找当前区间跨度最长的一段线段,然后不断递归。
Code

#include <bits/stdc++.h>
using namespace std;
const int N = 3e5 + 100;
int n, a[N], pos[N];
struct tnode
{
    int l, r, mx, mn;
};
struct segment_tree
{
    tnode t[N << 2];
    void pushup(int root)
    {
        int ch = root << 1;
        t[root].mx = max(t[ch].mx, t[ch + 1].mx);
        t[root].mn = min(t[ch].mn, t[ch + 1].mn);
    }
    void build(int root, int l, int r)
    {
        t[root].l = l;
        t[root].r = r;
        if(l != r)
        {
            int ch = root << 1;
            int mid = l + r >> 1;
            build(ch, l, mid);
            build(ch + 1, mid + 1, r);
            pushup(root);
        }
        else
        {
            t[root].mn = t[root].mx = a[l];
        }
    }
    int query_max(int root, int l, int r)
    {
        if(t[root].l >= l && t[root].r <= r)
        {
            return t[root].mx;
        }
        int ch = root << 1;
        int mid = t[root].l + t[root].r >> 1;
        if(r <= mid) return query_max(ch, l, r);
        else if(l > mid) return  query_max(ch + 1, l, r);
        else return max(query_max(ch, l, mid), query_max(ch + 1, mid + 1, r));
    }
    int query_min(int root, int l, int r)
    {
        if(t[root].l >= l && t[root].r <= r)
        {
            return t[root].mn;
        }
        int ch = root << 1;
        int mid = t[root].l + t[root].r >> 1;
        if(r <= mid) return query_min(ch, l, r);
        else if(l > mid) return  query_min(ch + 1, l, r);
        else return min(query_min(ch, l, mid), query_min(ch + 1, mid + 1, r));
    }
} st;
int cal(int l, int r)
{
    if(l + 1 == r) return 1;
    if(l >= r) return 0;
    int mxval = st.query_max(1, l, r);
    int mnval = st.query_min(1, l, r);
    int L = pos[mxval], R = pos[mnval];
    if(L > R) swap(L, R);
    return cal(l, L) + 1 + cal(R, r);
}
void solve()
{
    cin >> n;
    for(int i = 1; i <= n; ++i) cin >> a[i], pos[a[i]] = i;
    if(n == 1)
    {
        cout << "0\n";
        return;
    }
    st.build(1, 1, n);
    cout << cal(1, n) << "\n";
    int m;
}
signed main()
{
    ios::sync_with_stdio(false), cin.tie(0);
    int t;
    cin >> t;
    while(t--) solve();
    return 0;
}

E、Placing Jinas(补ing)

posted @ 2022-06-26 09:25  std&ice  阅读(68)  评论(0)    收藏  举报