Codeforces Round 906 (Div. 2) A-E1

比赛地址

A. Doremy's Paint 3

题意:给出一个数组b,问能否通过重新排序使得数组满足b1+b2=b2+b3=...=bn1+bn

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,构造一个操作序列,使得最后得到的字符串满足si=Sni+1(1in)

操作:向任意一个位置插入字符串"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个点,初始没有边的无向图,每次可以进行以下操作:

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

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

Solution

贪心,考虑u,v如果可以连接的话,假设au=u×v×c2

那么对于1,u,因为v2,所以auu×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个区间,区间范围是1lrn,第i个区间对[li,ri]进行+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 @   HikariFears  阅读(315)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
点击右上角即可分享
微信分享提示