Codeforces Round 906 (Div. 2) A-E1

比赛地址

A. Doremy's Paint 3

题意:给出一个数组\(b\),问能否通过重新排序使得数组满足\(b_1+b_2=b_2+b_3=...=b_{n-1}+b_{n}\)

Solution

首先判断元素个数

如果是1,则满足条件

如果是2,需判断不同元素个数的差是否小于等于1

其余的均不满足条件

void solve()
{
    int n;
    cin >> n;
    set<int> st;
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
        st.insert(a[i]);
    }
    if (st.size() == 1)
    {
        cout << "Yes\n";
    }
    else if (st.size() > 2)
    {
        cout << "No\n";
    }
    else
    {
        int cnt1 = 0, cnt2 = 0;
        for (int i = 1; i <= n; i++)
        {
            if (a[i] == a[1])
                cnt1++;
            else
                cnt2++;
        }
        if(abs(cnt1-cnt2)<=1)
        {
        	cout<<"Yes\n";
        }else
        {
        	cout<<"No\n";
        }
    }
}

B. Qingshan Loves Strings

题意:给出两个01串\(s,t\),问能否通过若干次(可以是0次)以下操作,使得\(s\)中相邻的字符都不同

操作:向\(s\)中任意一个位置插入字符串\(t\)

Solution

字符串\(t\)内的相邻元素都不同才可行,再考虑\(s\)的情况

如果\(s\)中有相邻的0,则\(t\)的最左和最右都必须是1

如果\(s\)中有相邻的1,则\(t\)的最左和最右都必须是0

如果既有相邻的0又有相邻的1,则不可行

void solve()
{
    int n, m;
    cin >> n >> m;
    string s, t;
    cin >> s >> t;
    int flag = 1;
    for (int i = 0; i < n - 1; i++)
    {
        if (s[i] == s[i + 1])
        {
            flag = 0;
            break;
        }
    }
    if (flag)
    {
        cout << "Yes\n";
        return;
    }
    flag = 1;
    for (int i = 0; i < m - 1; i++)
    {
        if (t[i] == t[i + 1])
        {
            flag = 0;
            break;
        }
    }
    if (!flag)
    {
        cout << "No\n";
        return;
    }
    int flag0 = 0, flag1 = 0;
    for (int i = 0; i < n - 1; i++)
    {
        if (s[i] == s[i + 1] && s[i] == '0')
        {
            flag0 = 1;
        }
        else if (s[i] == s[i + 1] && s[i] == '1')
        {
            flag1 = 1;
        }
    }
    if (t[0] != t[m - 1])
    {
        cout << "No\n";
        return;
    }
 
    if (flag0 && !flag1 && t[0] == '1')
    {
        cout << "Yes\n";
    }
    else if (!flag0 && flag1 && t[0] == '0')
    {
        cout << "Yes\n";
    }
    else
        cout << "No\n";
}

C. Qingshan Loves Strings 2

题意:给出一个01串\(s\),构造一个操作序列,使得最后得到的字符串满足\(s_i=S_{n-i+1}(1\le i \le n)\)

操作:向任意一个位置插入字符串\("01"\)

Solution

首先,原字符串的0和1的个数必须相同,不然无解

对于一个字符串,假设前\(x\)位和后\(x\)位已经满足条件了,那么继续考虑第\((x+1)\)

假设它们都是1,那么向左边的1的左边进行一次操作,这样会使得字符串变为\(...011...1...\)

假设它们都是0,那么向右边的0的右边进行一次操作,这样会使得字符串变为\(...0...001...\)

如此进行模拟即可

void solve()
{
    int n;
    cin >> n;
    string s;
    cin >> s;
    if (n & 1)
    {
        cout << "-1\n";
        return;
    }
    int flag = 1;
    int cnt1 = 0, cnt0 = 0;
 
    for (int i = 0; i < n / 2; i++)
    {
        if (s[i] != s[n - i])
        {
            flag = 0;
            break;
        }
    }
    if (flag)
    {
        cout << "0\n";
        cout << "\n";
        return;
    }
    for (int i = 0; i < n; i++)
    {
        if (s[i] == '1')
        {
            cnt1++;
        }
        else
            cnt0++;
    }
    if (cnt1 != cnt0)
    {
        cout << "-1\n";
        return;
    }
    for (int i = 501; i <= 500 + n; i++)
    {
        a[i] = s[i - 501] - '0';
    }
 
    int l = 501, r = 500 + n;
    int ll = 501, rr = 500 + n;
    vector<int> ans;
 
    while (l < r)
    {
        int len = rr - ll + 1;
        if (a[l] != a[r])
        {
            l++;
            r--;
        }
        else if (a[l] == 1)
        {
            ans.push_back(l - ll);
            a[l - 1] = 1;
            ll -= 2;
            l--;
            r--;
        }
        else
        {
            ans.push_back(len - (rr - r));
            a[r + 1] = 0;
            rr += 2;
            r++;
            l++;
        }
    }
    cout << ans.size() << "\n";
    for (auto it : ans)
    {
        cout << it << " ";
    }
    cout << "\n";
}

D. Doremy's Connecting Plan

题意:给出一个\(n\)个点,初始没有边的无向图,每次可以进行以下操作:

如果\(\sum \limits_S a_k >=i \times j \times c\)(S表示点\(i,j\)各自的联通分量的并集),则在\(i,j\)连接一条无向边

问是否能够使得无向图变成连通图

Solution

贪心,考虑\(u,v\)如果可以连接的话,假设\(a_u=\frac{u\times v \times c}{2}\)

那么对于\(1,u\),因为\(v \ge 2\),所以\(a_u \ge u \times c\)

所以如果可以连边,则一定可以把点1与其相连

struct node
{
    int x, y;
    bool operator<(const node &t) const &
    {
        if (y * k - x != t.y * k - t.x)
            return y * k - x < t.y * k - t.x;
        return y < t.y;
    }
} e[N];

void solve()
{

    cin >> n >> k;
    // vector<int> a(n + 1);
    for (int i = 1; i <= n; i++)
    {
        int x;
        cin >> x;
        a[i] = x;
        e[i].x = x;
        e[i].y = i;
    }
    sort(e + 2, e + 1 + n);
    for (int i = 2; i <= n; i++)
    {
        if (a[1] + e[i].x < e[i].y * k)
        {
            cout << "No\n";
            return;
        }
        else
        {
            a[1] += e[i].x;
        }
    }
    cout << "Yes\n";
}

E1. Doremy's Drying Plan (Easy Version)

题意:初始\([1,n]\)全为0,给出\(m\)个区间,区间范围是\(1 \le l \le r \le n\),第\(i\)个区间对\([l_i,r_i]\)进行+1操作,现在最多可以删去两个区间,问删完后\([1,n]\)有多少个点是0

Solution

我们先假设不删任何区间,最后得到的\([1,n]\)的情况

对于每个区间,它们覆盖的点的大小可能是1,2,...,m

考虑两种情况:

1.删去两个覆盖点的大小为1数量最多的区间

2.枚举所有大小为2的点,我们可以处理出来哪对区间覆盖在了这个点上面,然后分别统计删去了这些区间对后的答案即可

void solve()
{
    int n, m, k;
    cin >> n >> m >> k;
    for (int i = 1; i <= n; i++)
    {
        a[i] = a0[i] = a1[i] = vis[i] = 0;
    }
    vector<node> v;
    for (int i = 1; i <= m; i++)
    {
        cin >> l[i] >> r[i];
        v.push_back({l[i], 1, i});
        v.push_back({r[i] + 1, -1, i});
    }
 
    for (int i = 1; i <= m; i++)
    {
        a[l[i]]++;
        a[r[i] + 1]--;
    }
 
    for (int i = 1; i <= n; i++)
    {
        a[i] = a[i - 1] + a[i];
    }
 
    for (int i = 1; i <= n; i++)
    {
        a0[i] = a0[i - 1] + (a[i] == 0);
        a1[i] = a1[i - 1] + (a[i] == 1);
    }
 
    int cnt0 = a0[n];
    int cnt1 = 0;
    vector<int> v1;
    for (int i = 1; i <= m; i++)
    {
        v1.push_back(a1[r[i]] - a1[l[i] - 1]);
    }
    sort(v1.begin(), v1.end());
    sort(v.begin(), v.end());
    int ans = cnt0 + v1[m - 1] + v1[m - 2];
 
    map<pii, int> mp;
    set<int> st;
    int pos = 0;
    for (int i = 1; i <= n; i++)
    {
        while (pos < (int)(v.size()) && v[pos].x == i)
        {
            if (v[pos].y == 1)
            {
                st.insert(v[pos].idx);
            }
            else
            {
                st.erase(v[pos].idx);
            }
            pos++;
        }
        if (st.size() == 2)
        {
            int x = *(st.begin()), y = *(st.rbegin());
            if (x > y)
                swap(x, y);
            mp[{x, y}]++;
            // cout<<i<<":"<<x<<" "<<y<<"\n";
        }
    }
    for (auto &it : mp)
    {
        int xx = it.first.first, yy = it.first.second;
        int res1 = a1[r[xx]] - a1[l[xx] - 1];
        int res2 = a1[r[yy]] - a1[l[yy] - 1];
        int sum = it.second + res1 + res2;
        ans = max(ans, sum + cnt0);
    }
 
    cout << ans << "\n";
}
posted @ 2023-10-30 11:40  HikariFears  阅读(335)  评论(0)    收藏  举报