Codeforces Round #753 (Div. 3)(A~E)题解

传送门
在这里插入图片描述
在这里插入图片描述

题目大意

假定第一行给出如下:abcdefghijklmnopqrstuvwxyz
我们可以发现a在第一个位置,c在第三个位置
那么我们要打出ac这个字符串手指就需要移动2下
问给出一个字符串,手指需要移动几下才能打出来

解题思路

通过一维数组记录每一个字符的位置,然后每两个相邻的字符通过位置差可以得到手指移动的次数。

解题代码

#include<bits/stdc++.h>
using namespace std;

#define IO ios::sync_with_stdio(0),cin.tie(0)
#define debug(a) cout << #a << ' ' << a << endl;
void in_out()
{
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
}

int a[30];

void solve()
{
    string s;
    cin >> s;
    for(int i = 0;i < s.length();++i) {
        a[s[i] - 'a'] = i;
    }
    string s1;
    cin >> s1;
    int ans = 0,pre = a[s1[0]-'a'];
    for(int i = 1;i < s1.length();++i) {
        ans = ans + fabs(a[s1[i] - 'a'] - pre);
        // cout << ans << endl;
        pre = a[s1[i] - 'a'];
    }
    cout << ans << endl;
}

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

在这里插入图片描述
在这里插入图片描述

题目大意

给出两个数a,b
a是初始位置,b是移动次数
假如当前位置是奇数会向右移动i个单位(i表示第i次移动)
假如当前位置是偶数会向左移动i个单位 (i表示第i次移动)
问b次移动后,当前位置是哪里

解题思路

对于模拟题,可以通过模拟题意的执行,来寻找规律。
具体规律见代码。

解题代码

#include<bits/stdc++.h>
using namespace std;

#define IO ios::sync_with_stdio(0),cin.tie(0)
#define debug(a) cout << #a << ' ' << a << endl;
#define LL long long
void in_out()
{
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
}

void solve()
{
    LL x0,n;
    cin >> x0 >> n;
    LL ans = 0;
    if(x0%2 == 0) {
        if(n%4 == 0) cout << x0 << endl;
        else if(n%4 == 1) cout << x0-n << endl;
        else if(n%4 == 2) cout << x0+1ll << endl;
        else cout << x0+n+1ll << endl;
    }
    else {
        if(n%4 == 0) cout << x0 << endl;
        else if(n%4 == 1) cout << x0+n << endl;
        else if(n%4 == 2) cout << x0-1ll << endl;
        else cout << x0-n-1ll << endl;
    }
}

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

在这里插入图片描述
在这里插入图片描述

题目大意

给出一个长为n的数组,我们每次可以将数组中的最小数取出来,然后给剩余数字都减去取出的数字。
问数组在变换过程中,出现的最小值的最大数是多少。

解题思路

我们现提出一个值得去摒弃的假思路,然后再推翻它求出正解。
首先,当n为1时,结果很显然为a[1]
当n不为1时,很显然结果不会是一个负数。
那么我们将所有负数都取出来,这就是结果吗?
显然,如果通过感觉我们也许会认为如果取出一个正数,那么所有数字都会降低,是不划算的。
但是,在[1,2,7]这个数组中我们却发现了最佳的答案是4而不是1
这是因为,7在降低的过程中,数组的最小值也被去除,如果7下降的值大于了数组当前的最小值,那么我们就可以取出最小值来提高数组当中的最小值
通过多次举例,我们会发现并没有出现一个完美的贪心思路。
查看数据范围,我们发现完全可以枚举每一个阶段的数组最小值,这也正是此题的正解。

解题代码

#include<bits/stdc++.h>
using namespace std;

#define IO ios::sync_with_stdio(0),cin.tie(0)
#define LL long long
const int maxn = 2e5+10;
LL a[maxn];

void in_out()
{
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
}

void solve()
{
    int n;
    cin >> n;
    priority_queue<LL,vector<LL>,greater<LL> > q;
    while (q.size() > 0) q.pop();
    for(int i = 1;i <= n;++i) cin >> a[i],q.push(a[i]);
    LL ans = -1e9-10,pre = 0;
    while (q.size() > 0)
    {
        LL x = q.top();
        q.pop();
        x += pre;
        ans = max(ans,x);
        // cout << "ans:" << ans << endl;
        pre -= x;
    }
    cout << ans << endl;
}

int main()
{
    // in_out();
    IO;
    int t;
    cin >> t;
    while (t--)
    {
        solve();
    }
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

题目大意

题中会给出一个数组,每一个数组元素都有一个属性红或者蓝
蓝属性元素可以降低到任意值,红属性元素可以增加到任意值
问给出的数组通过红蓝变换能否实现1到n每个数字只出现一次

解题思路

这里有一个重要的思路,就是反向思考。
题中问什么情况可,我们就去想什么情况不可
如果在蓝元素中,出现了1,1,2,3就不可以
为什么呢?因为如果前m个蓝色元素出现了两次小于m的元素,那么数组无论如何变幻,小于m的元素数量永远大于m个,这说明前m-1个元素必定会有重复的。
在红色元素中,也有同样的道理。
仔细思考,除了这两种情况,还有其他情况会出现不可行状态吗?

解题代码

#include<bits/stdc++.h>
using namespace std;

#define IO ios::sync_with_stdio(0),cin.tie(0)
#define LL long long
const int maxn = 2e5+10;
int a[maxn];
vector<int> l,r;

void in_out()
{
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
}


void solve()
{
    int n;
    cin >> n;
    l.clear(),r.clear();
    for(int i = 1;i <= n;++i) cin >> a[i];
    string s;
    cin >> s;
    for(int i = 0;i < n;++i) {
        if(s[i] == 'B') l.push_back(a[i+1]);
        else r.push_back(a[i+1]);
    }   
    sort(l.begin(),l.end());
    sort(r.begin(),r.end());
    reverse(r.begin(),r.end());
    bool si = true;
    for(int i = 0;i < l.size();++i) {
        if(l[i] < (i+1)) {
            si = false;
            break;
        }
        // cout << l[i] << endl;
        // cout << "si" << si << endl;
    }
    for(int i = 0;i < r.size();++i) {
        if(r[i] > (n-i)) {
            si = false;
            break;
        }
        // cout << "si" << si << endl;
    }
    if(si) cout << "YES" << endl;
    else cout << "NO" << endl;
}

int main()
{
    // in_out();
    IO;
    int t;
    cin >> t;
    while (t--)
    {
        solve();
    }
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

题目大意

就是说给定了n*m个框,然后给出一个人行动的轨迹上下左右
问这个人初始状态在哪个点的时候,能够行动的数量最多

解题思路

我们就假定自己是那个人,我们有一个套完备的行走策略。
当我们想要通过这个策略在这个空间中行走最多次数时,我们应该在哪个地方。这其实很像一个贪心的思维。
我们假定他一直向左走,那么我们就就希望初始位置在最右边
当左右移动的最大位置差大于m的时候此时也正是我们无路可走的时候。
上下行走同理。
这样,我们就得出了行走的奥妙了

解题代码

#include<bits/stdc++.h>
using namespace std;

#define IO ios::sync_with_stdio(0),cin.tie(0)
void in_out()
{
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
}


void solve()
{
    int n,m;
    cin >> n >> m;
    string s;
    cin >> s;
    int l = 0,r = 0,u = 0,d = 0;
    pair<int,int> p;
    p.first = p.second = 0;
    for(int i = 0;i < s.length();++i) {
        if(s[i] == 'L')  {
            p.first -= 1;
            l = min(l,p.first);
        }
        else if(s[i] == 'R') {
            p.first += 1;
            r = max(r,p.first);
        }
        else if(s[i] == 'U') {
            p.second += 1;
            u = max(u,p.second);
        }
        else {
            p.second -= 1;
            d = min(d,p.second);
        }
        if(r-l >= m ) {
            if(s[i] == 'L') l += 1;
            else  r -= 1;
            break;
        }
        else if(u-d >= n) {
            if(s[i] == 'U') u -= 1;
            else d += 1;
            break;
        }
    }
    cout << n-(-1*d) << ' ' << -1*l+1 << endl;
}

int main()
{
    // in_out();
    IO;
    int t;
    cin >> t;
    while(t--) {
        solve();
    }
    return 0;
}

本次总结

第一题,签到
第二题,简单推理
第三题,抽象模拟
第四题,归纳总结,逆向思维
第五题,贪心思考,求解最佳
纵观本场题目,出题人想必十分善于观察细小甚微的东西,从小小的规律中探寻出一条大道真知。不得不说,我十分敬佩这一场比赛的出题人。在高速发展的当今社会,能够静下心来去观察一下细小的规律,并试图在其中寻找人们所认同的公理甚至说真理,这是值得我去学习的。
同时,这场比赛中我也学习到了,各种基础思维的组合使用。
总而言之,这一场比赛的参与是我的荣幸。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值