CodeForces Round #859 (div.4) A~G

A. Plus or Minus(签到)

题目链接

题意

判断 a + b = c a + b = c a+b=c 是否成立,成立输出 + ,否则输出 - .

思路

签到

代码

#include <bits/stdc++.h>
#define ll long long
#define endl '\n'
using namespace std;
const int N = 2e5 + 10;

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

    if (a + b == c) cout << "+" << endl;
    else cout << "-" << endl;
}

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

    return 0;
}

B. Grab the Candies(贪心)

题目链接

题意

给定一个长度为 n n n 的数组,A 和 B 依次轮流拿数,A 拿偶数,B 拿奇数,问能否保证任何时候 A 手中的数的总和都大于 B 。

思路

贪心。

偶数全给 A,奇数全给 B,最后比较大小,要求 suma > sumb

代码

#include <bits/stdc++.h>
#define ll long long
#define endl '\n'
using namespace std;
const int N = 2e5 + 10;

void solve()
{
    int n;
    cin >> n;

    int suma = 0, sumb = 0;
    for (int i = 1; i <= n; i++)
    {
        int x;
        cin >> x;
        if (x % 2 == 0){
            suma += x;
        }
        else {
            sumb += x;
        }
    }

    if (suma <= sumb)
        cout << "NO" << endl;
    else cout << "YES" << endl;
}

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

    return 0;
}

C. Find and Replace(找规律)

题目链接

题意

给定一个长度为 n n n 的仅包含小写字母的字符串,每次操作可以将每种字符变成 01 ,操作不限次数。

问最终能否形成一个 01 01 01 串,使得没有连续的 01 ,即 01 01 01 相互间隔排列,如: 010101 010101 010101

思路

如果两个相同字符之间包含 偶数 个其他字符,则不能形成 01 01 01 串,反之可以。

枚举 26 个字母的位置,依次判断两个相同字母之间的字符是否是奇数个即可。

代码

#include <bits/stdc++.h>
#define ll long long
#define endl '\n'
using namespace std;
const int N = 2010;

void solve()
{
    int n;
    cin >> n;
    string s; cin >> s;
    
    vector<vector<int>> p(30);
    for (int i = 0; i < n; i++){
        p[s[i] - 'a'].push_back(i);
    }

    int f = 0;
    for (int i = 0; i < 26; i++){
        if (p[i].empty()) continue;

        int last = p[i][0];
        for (auto pos : p[i]){
            if ((pos - last - 1) % 2 == 0){
                f = 1;
                break;
            }
            last = pos;
        }
    }

    if (f) cout << "NO" << endl;
    else cout << "YES" << endl;
}

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

    return 0;
}

D. Odd Queries(前缀和)

题目链接

题意

给定一段长度为 n n n 的序列和 q q q 次询问,每次询问给定 l l l r r r k k k ,表示将区间 l,r 中的所有数都变成 k ,问每次变化后整个序列的和是多少。

思路

先预处理好前缀和,然后求出询问区间变化后的值,最后替换原区间得到整个序列和。

代码

#include <bits/stdc++.h>
#define ll long long
#define endl '\n'
using namespace std;
const int N = 2e5 + 10;

int n, q;
int a[N];
ll s[N];

void solve()
{
    cin >> n >> q;
    for (int i = 1; i <= n; i++){
        cin >> a[i];
        s[i] = s[i - 1] + a[i];
    }

    while (q--)
    {
        int l, r, x;
        cin >> l >> r >> x;
        ll sum = (r - l + 1) * x;

        if ((s[n] - s[r] + s[l - 1] + sum) % 2)
            cout << "YES" << endl;
        else cout << "NO" << endl;
    }
}

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

    return 0;
}

E. Interview(二分)

题目链接

题意

给定 n n n 个堆,第 i i i 个堆有 i i i1 ,也就是说第 i i i 个堆的大小为 i i i ,但是此时有一个 2 ,使得某一个堆的大小为 i + 1 i + 1 i+1 ,现在要你找出来这个堆是哪一个。

思路

交互题,根据每次 “?” 后猜测的区间给出相应的区间和,直到猜到目标堆,输出 “!” 和目标堆的序号。

因为数据不超过 2 ⋅ 1 0 5 2 · 10^5 2105 ,最多需要 ⌈ l o g 2 ( 2 ⋅ 1 0 5 ) ⌉ = 18 ⌈log2(2⋅10^5)⌉=18 log2(2105)⌉=18 次查询,远低于 30 30 30 ,所以可以使用二分来查找。

每次判断区间和是否等于给出的答案,如果等于则表示答案在另一段区间内,如果比给出的答案小 1 1 1 ,则在该区间内,继续对该区间二分。

代码

#include <bits/stdc++.h>
#define ll long long
#define endl '\n'
using namespace std;
const int N = 2e5 + 10;

int a[N];
ll s[N];

void solve()
{
    int n;
    cin >> n;

    for (int i = 1; i <= n; i++){
        cin >> a[i];
        s[i] = s[i - 1] + a[i];
    }

    int l = 1, r = n;
    ll res = 0;
    while (l < r)
    {
        int mid = (l + r) / 2;

        cout << "? " << (mid - l + 1) << ' ';
        for (int i = l; i <= mid; i++)
            cout << i << ' ';
        cout << endl << flush;

        int x;
        cin >> x;
        if (x == s[mid] - s[l - 1])
            l = mid + 1;
        else r = mid;
    }

    cout << "! " << r << endl << flush;
}

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

    return 0;
}

F. Bouncy Ball(模拟)

题目链接

题意

给定一个 n × m 的地图,其中有一个小球,规定其移动方向为:

​ DR:右下↘

​ DL:左下↙

​ UR:右上↗

​ UL:左上↖

每次碰到边缘时会按照折射原理改变方向,如果是角落就按相反方向原路返回。

给出起点 ( x 1 , y 1 ) (x_1, y_1) (x1,y1) 和终点 ( x 2 , y 2 ) (x_2, y_2) (x2,y2) 和一个初始方向,问能否从起点到达终点。

如果能,输出改变方向的次数,若不能则输出 − 1 -1 1

思路

模拟。

dxdy 记录当前的方向,当碰到边缘壁时,判断是否在角落,改变方向和坐标并记录次数,直到到达终点。

代码

#include <bits/stdc++.h>
#define ll long long
#define endl '\n'
#define y1 y
using namespace std;
const int N = 2e5 + 10;

int n, m;
int x1, y1, x2, y2;

void solve()
{
    cin >> n >> m;
    cin >> x1 >> y1 >> x2 >> y2;
    string op;
    cin >> op;

    int dx = 1, dy = 1;
    if (op[0] == 'U') dx = -1;
    if (op[1] == 'L') dy = -1;

    int s = 4 * n * m + 10;
    int res = 0;
    while (s--)
    {
        if (x1 == x2 && y1 == y2){
            cout << res << endl;
            return;
        }

        bool f1 = (x1 + dx < 1 || x1 + dx > n);
        bool f2 = (y1 + dy < 1 || y1 + dy > m);
        res += (f1 || f2);

        //如果到了角落,则反方向
        if (f1) dx *= -1;
        if (f2) dy *= -1;

        x1 += dx;
        y1 += dy;
    }

    cout << -1 << endl;
}

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

    return 0;
}

G2. Subsequence Addition (Hard Version)(前缀和)

题目链接

题意

给定一个长度为 n n n 的目标序列,问能否由初始元素 1 1 1​ 构造而成。

1 1 1 可以用无限次,但最初序列中只有一个 1 1 1​ ,每次可以合并若干个数得到一个新的数。

若能得到该序列输出 “YES” ,否则输出 “NO” 。

思路

首先目标序列中必须要有至少一个 1 1 1 ,否则不可能进行合成构造,所以先特判目标序列中是否有 1 1 1

可以先进行排序再判断第一个数。

然后由于目标序列中所有大于 1 1 1 的数都是由小的数合成而来的,所以如果所有比它小的数加起来都不能大于或等于它,那么这个数就无法得到,即无法构造出来。

所以我们可以使用 前缀和 来判断这个数能否被构造出来,只要这个数前面数的前缀和小于它则一定不能。

代码

#include <bits/stdc++.h>
#define ll long long
#define endl '\n'
using namespace std;
const int N = 2e5 + 10;

int n;
int a[N];

void solve()
{
    cin >> n;
    for (int i = 1; i <= n; i++){
        cin >> a[i];
    }

    sort(a + 1, a + 1 + n);

    if (a[1] != 1){
        cout << "NO" << endl;
        return;
    }

    ll sum = a[1];
    for (int i = 2; i <= n; i++){
        if (sum < a[i]){
            cout << "NO" << endl;
            return;
        }
        
        sum += a[i];
    }

    cout << "YES" << endl;
}

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

    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BraumAce

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值