Codeforces Round #829 (Div. 2)

比赛链接:https://codeforces.com/contest/1754
A. Technical Support
题目大意:一个字符串表示消息记录,Q代表发送的询问,A代表发送的回答,回答可能有延迟,要求有问有答
题解:任意后缀A需大于Q

#include <bits/stdc++.h>

using namespace std;

const int N = 3 * 1e5;

typedef long long ll;

char s[N];

void solve()
{
    int n;
    cin >> n;
    cin >> s + 1;
    map<char, int> mp;
    string ans = "Yes";
    for(int i = n; i >= 1; i -- )
    {
        mp[s[i]] ++ ;
        if(mp['A'] < mp['Q']) ans = "No";
    }
    cout << ans << endl;
}

int main()
{
    int T;
    cin >> T;
    while(T -- ) solve();
}

B. Kevin and Permutation
题目大意:求1~n的一个排列使得差分序列的最小值最大
题解:最小值为⌊n/2⌋

#include <bits/stdc++.h>

using namespace std;

const int N = 3 * 1e5;

void solve()
{
    int n;
    cin >> n;
    for(int i = 1; i <= n / 2; i ++ )
    {
        cout << i + n / 2 << ' ';
        cout << i << ' ';
    }

    if(n & 1) cout << n;
    cout << endl;

}

int main()
{
    int T;
    cin >> T;
    while(T -- ) solve();
}

C1/2. Make Nonzero Sum
题目大意:讲序列a拆分成任意长度大于等于1的段,每段的值为Si,要求所有的段加起来等于0
题解:状态机DP,可以抽象看成两条个序列,分别为
v[1] -v[2] v[3] -v[4]…
-v[1] v[2] -v[3] v[4]…
再抽象看成
第一段肯定是第一个序列的前缀,分段等价于转换序列,因为第i段的一个值必定是正的
所以第一个序列只能在奇数处转换到第二个序列,这样后面的段第一个值才能为正
同理第二个序列在偶数处转换序列
f[i][j]代表结尾处在第j+1个序列,取得的最小绝对值

#include <bits/stdc++.h>

using namespace std;

const int N = 3 * 1e5;

typedef long long ll;
typedef pair<int, int> PII;

int a[N], b[N]; //两个序列
int f[N][2];
int g[N][2]; // 记录状态转换

void solve()
{
    int n;
    cin >> n;
    for(int i = 1; i <= n; i ++ )
    {
        int x;
        cin >> x;
        a[i] = (i & 1) ? x : -x;
        b[i] = (i & 1) ? -x : x;
    }

    f[1][0] = a[1];
    f[1][1] = 1e9;
    for(int i = 2; i <= n; i ++ )
    {
        if(i % 2 == 0)
        {
            f[i][0] = f[i - 1][0] + a[i];
            g[i][0] = 0;
            if(abs(f[i - 1][1] + b[i]) < abs(f[i - 1][0] + b[i]))
            {
                f[i][1] = f[i - 1][1] + b[i];
                g[i][1] = 1;
            }
            else
            {
                f[i][1] = f[i - 1][0] + b[i];
                g[i][1] = 0;
            }
        }
        else
        {
            f[i][1] = f[i - 1][1] + b[i];
            g[i][1] = 1;
            if(abs(f[i - 1][1] + a[i]) < abs(f[i - 1][0] + a[i]))
            {
                f[i][0] = f[i - 1][1] + a[i];
                g[i][0] = 1;
            }
            else
            {
                f[i][0] = f[i - 1][0] + a[i];
                g[i][0] = 0;
            }
        }
    }

    if(min(abs(f[n][0]), abs(f[n][1]))) cout << -1 << endl;
    else
    {
        int l = n, r = n, t = abs(f[n][1]) < abs(f[n][0]);
        vector<PII> ans;
        for(int i = n; i >= 2; i -- )
            if(t != g[i][t])
            {
                ans.push_back({l, r});
                l = i - 1;
                r = i - 1;
                t = g[i][t];
            }
            else l -- ;
        ans.push_back({l, r});
        cout << ans.size() << endl;
        sort(ans.begin(), ans.end());
        for(auto [x, y] : ans)
            cout << x << ' ' << y << endl;
    }
}

int main()
{
    int T;
    cin >> T;
    while(T -- ) solve();
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值