Codeforces Round 986 (Div. 2) ABCD补题

链接:

Codeforces Round 986 (Div. 2)

A:Alice's Adventures in ''Chess''

大意:

       在二维坐标上循环移动能否到某一点

思路:

       数据范围很小,多循环几次,

        最少21次,题解说的,不太确定,循环1000次都行,反正别循环10就行了

代码:

#include <bits/stdc++.h>
#include <array> 
using namespace std;
#define int long long
const int N = 1e5 + 10, INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
#define pb push_back
#define  vi vector<int>
#define  vvi vector<vector<int>>
#define  vii vector<pair<int, int>>
#define ff first 
#define ss second 
// ++   ~!    */+-    <<>>    <>  ==   &^|   &&|| =



void solve() 
{
    int n, a, b;cin >> n >> a >> b;
    string s;cin >> s;
    
    map<char, pair<int, int>> dir;
    dir['N'] = { 0, 1 };
    dir['E'] = { 1, 0 };
    dir['S'] = { 0, -1 };
    dir['W'] = { -1, 0 };

    int x = 0, y = 0;
    int t = 100;
    while (t--)
    {
        for (int i = 0; i < n; i++)
        {
            int r = x + dir[s[i]].ff, c = y + dir[s[i]].ss;
            if (r == a && c == b)
            {
                cout << "Yes" << endl;
                return;
            }
            x = r, y = c;
        }
    }

    cout << "No" << endl;


}



signed main()
{
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);

    int t = 1;
    cin >> t;
    while (t--) solve();

    return 0;
}
/*   /\_/\
*   (= ._.)
*   / >  \>
*/

 B:Alice's Adventures in Permuting

大意:

        给长度为n的a[i]表达式,每次可把最大的数变成数组的mex值,求需要几次运算

思路:

        b等于零的情况下c < n - 2是没结果的,n-1 n-2都是需要n-1次,大于等于n就是n次都换了

        b不等于0话a[i]就没重复的,大于n - 1的数的数量就是结果

代码:

#include <bits/stdc++.h>
#include <array> 
using namespace std;
#define int long long
const int N = 1e5 + 10, INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
#define pb push_back
#define  vi vector<int>
#define  vvi vector<vector<int>>
#define  vii vector<pair<int, int>>
#define ff first 
#define ss second 
// ++   ~!    */+-    <<>>    <>  ==   &^|   &&|| =



void solve() 
{
    int n, b, c;cin >> n >> b >> c;

    if (b == 0)
    {
        if (c < n - 2)cout << -1 << endl;
        else if (c == n - 2)cout << n - 1 << endl;
        else if (c == n - 1)cout << n - 1 << endl;
        else cout << n << endl;

        return;
    }

    if (c > n - 1)cout << n << endl;
    else 
    {
        int num = (n - 1 - c) / b + 1; // 在0,n - 1范围内的数
        cout << n - num << endl;
    }

}

signed main()
{
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);

    int t = 1;
    cin >> t;
    while (t--) solve();

    return 0;
}
/*   /\_/\
*   (= ._.)
*   / >  \>
*/

C:Alice's Adventures in Cutting Cake

大意:

        一个数组,分成m + 1个区间,使得有m个区间大于给定值的数,求在这种情况下得到的剩下的数的最大值

思路:

        由于是连续的,对于要获得的区间,左边和右边一定是按照区间和大于v就分段的,

        在这种情况下,从前往后、从后往前分别求最小的第i个大于v的区间端点,然后前后结合一下,左边右边加起来等于m,那么中间就是最优结果

代码:

#include <bits/stdc++.h>
#include <array> 
using namespace std;
#define int long long
const int N = 2e5 + 10, INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
#define pb push_back
#define  vi vector<int>
#define  vvi vector<vector<int>>
#define  vii vector<pair<int, int>>
#define ff first 
#define ss second 
// ++   ~!    */+-    <<>>    <>  ==   &^|   &&|| =



int n, m, v, s[N], pf[N], sf[N];
void solve() {
	cin >> n >> m >> v;
	for (int i = 1;i <= n;i++)
	{
		cin >> s[i];
		s[i] += s[i - 1];
	}

	int s1 = 0, s2 = 0;
	for (int i = 1, lst = 0;i <= n; i ++)
		if (s[i] - s[lst] >= v)pf[++s1] = lst = i; // 找前缀第s1个v所在位置

	sf[0] = n + 1;
	for (int i = n, lst = n + 1;i >= 1; i --) // 找后缀第s2个v所在位置
		if (s[lst - 1] - s[i - 1] >= v)sf[++s2] = lst = i;
	
	if (s1 < m)
	{
		cout << -1 << endl;
		return;
	}

	int ans = -1;
	
	for (int i = 0; i <= m; i++)
		if (pf[i] < sf[m - i])ans = max(ans, s[sf[m - i] - 1] - s[pf[i]]);
	cout << ans << endl;
}

signed main()
{
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);

    int t = 1;
    cin >> t;
    while (t--) solve();

    return 0;
}
/*   /\_/\
*   (= ._.)
*   / >  \>
*/

D:Alice's Adventures in Cards

大意:

        Alice跟三个人换牌,自己有一张1,其他人1-n都有,目标换到n

        她的换牌原则是只换比自己手里大的

        其他三人只换权重大的,即a[i]>a[j],可以用j换j

思路:

        从后往前找合法转移状态,i可以换n,j可以换i,k可以换j......就这样去往下找到1,记下往后的地址,如果1没有,就输出no,要不就输出结果

       从提交里翻出来的代码,官方的总是看着不太好,民间的代码太长也不想看,太短又看不懂

代码:

#include <bits/stdc++.h>
#include <array> 
using namespace std;
#define int long long
const int N = 2e5 + 10, INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
#define pb push_back
#define  vi vector<int>
#define  vvi vector<vector<int>>
#define  vii vector<pair<int, int>>
#define ff first 
#define ss second 
// ++   ~!    */+-    <<>>    <>  ==   &^|   &&|| =

int a[3][N];
char s[] = "qkj";
int n;
void solve() 
{
    cin >> n;
    for (int i = 0; i < 3; i++)
        for (int j = 1; j <= n; j++)
            cin >> a[i][j];

    int lst[] = {n, n, n}; // 倒着推转移状态,这里的值是表示合法转状态里权值最小的位置,这样会更容易被换
    vii trans(n + 1, {0, -1});
    for (int i = n - 1; i > 0; i--)
    {
        int tmp = -1;
        for (int j = 0; j < 3; j ++) // 看能否用i从三人那往后换
            if (a[j][i] > a[j][lst[j]])
                tmp = j; //随便找个合法的就行
        if (tmp == -1)continue; // 没找到合法的,那么i不是好状态

        trans[i] = { tmp, lst[tmp] }; // 表示i可以与tmp换,换成lst[tmp]

// 更新lst,现在i是合法转移状态,lst[j]也是合法转移状态,当然是权值最小的最好获得,所以要更新一下
        for (int j = 0; j < 3; j++) 
            if (a[j][i] < a[j][lst[j]])lst[j] = i;  
    }
    // 从n往下会有很多叉路,但从1到n的路就一条,这就是树
    if (trans[1].second == -1)
    {
        cout << "NO" << endl;
        return;
    }
    cout << "YES" << endl;

    auto t = trans[1];
    vector <pair< char, int >> ans;
    while (1)
    {
        ans.push_back({ s[t.ff], t.ss });
        if (t.ss == n)break;
        t = trans[t.ss];
    }
    cout << ans.size() << endl;
    for (auto it : ans)
        cout << it.ff << ' ' << it.ss << endl;
}

signed main()
{
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);

    int t = 1;
    cin >> t;
    while (t--) solve();

    return 0;
}
/*   /\_/\
*   (= ._.)
*   / >  \>
*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值