Codeforces Round #776 (Div. 3)

A - Deletions of Two Adjacent Letters

题意

每次选择任意两个相邻的两个字符删除,问最后是否能得到给定的字符

题解

我们发现,因为每次都是选择两个相邻的字符,那么我们想要保留下来的答案的两端绝对不能出现奇数长度,也就是说,这个字符必须在对应下标的奇数位上(下标从1开始)

那么我们只需要看看原串的奇数位中有没有出现我们想要的字符就可以了

Code

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <map>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#include <sstream>
#include <unordered_map>
#define ll long long
#define ull unsigned long long
#define re return
#define pb push_back
#define Endl "\n"
#define endl "\n"
#define x first
#define y second
#define all(x) (x).begin(),(x).end()

using namespace std;

typedef pair<int, int> PII;

const int N = 1e5 + 10;
const int M = 1e5 + 10;
const int mod = 1000000007;
const int INF = 0x3f3f3f3f;

int dx[4] = {-1,0,1,0};
int dy[4] = {0,1,0,-1};

int T;
string s;
char c;

void solve(){
    cin >> s;
    cin >> c;
    for (int i = 0; i < s.size(); i += 2){
        // cout << s[i] << ' ';
        if(s[i] == c){
            cout << "YES" << Endl;
            re;
        }
    }
    cout << "NO" << Endl;
}

int main(){
    // ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    T = 1;
    cin >> T;
    while(T--){
        solve();
    }
}

B - DIV + MOD

题意

给定l和r,问在这个区间中选数x,使得 f a ( x ) = ⌊ x a ⌋ + x   m o d   a f_a(x)=\left\lfloor\frac{x}{a}\right\rfloor + x \bmod a fa(x)=ax+xmoda最大的最大值是多少

题解

我们知道,x%a的最大值就是a-1,而前面的答案在取的时候是慢慢的递增的,如果使x%a最大,也就是取得在r以内能被a整除的最大值减一,即 r / a ∗ a − 1 r/a*a-1 r/aa1,而如果这个数不在这个lr区间内,那么说明我们当前的区间在 x / a x/a x/a的情况下都是相等的,所以 f a ( r ) f_a(r) fa(r)也是一种可能的最大值

因为我们不能判断两者的最大值在某个数的情况下最大,所以我们可以直接取max

Code

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <map>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#include <sstream>
#include <unordered_map>
#define ll long long
#define ull unsigned long long
#define re return
#define pb push_back
#define Endl "\n"
#define endl "\n"
#define x first
#define y second
#define all(x) (x).begin(),(x).end()

using namespace std;

typedef pair<int, int> PII;

const int N = 1e5 + 10;
const int M = 1e5 + 10;
const int mod = 1000000007;
const int INF = 0x3f3f3f3f;

int dx[4] = {-1,0,1,0};
int dy[4] = {0,1,0,-1};

int T;
int l, r, a;

void solve(){
    cin >> l >> r >> a;
    int x = r / a * a - 1;
    int res1 = r / a + r % a;
    int res2 = 0;
    if(x >= l)
        res2 = x / a + x % a;
    cout << max(res1, res2) << endl;
}

int main(){
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    T = 1;
    cin >> T;
    while(T--){
        solve();
    }
}

C - Weight of the System of Nested Segments

题意

给定m个点,给定每个点的权值和在数轴上的坐标,嵌套的构成系统,每一个连线都要严格的在外面的圈内,问怎么构造n个系统,使得选取的2*n个点的权值最小

题解

和最小肯定是取前2n个最小值来构造答案

我们按权值排序,选取其中2n个点,然后按照这些2n个点的坐标来排序即可,然后俩俩选取

(这里是求加和的最小值,而不是比如问两个端点乘积后加和的最小值等对计算顺序有影响的操作,所以哪几个构成系统顺序是无所谓的,只要是那几个点就行,我就是因为这里卡主了不敢动手

Code

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <map>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#include <sstream>
#include <unordered_map>
#define ll long long
#define ull unsigned long long
#define re return
#define pb push_back
#define Endl "\n"
#define endl "\n"
#define x first
#define y second
#define all(x) (x).begin(),(x).end()

using namespace std;

typedef pair<int, int> PII;

const int N = 2e5 + 10;
const int M = 1e5 + 10;
const int mod = 1000000007;
const int INF = 0x3f3f3f3f;

int dx[4] = {-1,0,1,0};
int dy[4] = {0,1,0,-1};

int T;
int n, m;

struct nope
{
    int x, w, id;
} a[N];

void solve(){
    cin >> n >> m;
    for (int i = 1; i <= m; i++){
        cin >> a[i].x >> a[i].w;
        a[i].id = i;
    }
    sort(a + 1, a + 1 + m, [](nope a, nope b)
         { return a.w < b.w; });

    int summ = 0;
    for (int i = 1; i <= 2 * n; i++){
        summ += a[i].w;
    }
    cout << summ << endl;
    sort(a + 1, a + 1 + 2 * n, [](nope a, nope b)
         { return a.x < b.x; });

    for (int i = 1, j = 2 * n; i <= n; i++, j--){
        cout << a[i].id << ' ' << a[j].id << endl;
    }
    cout << endl;
}

int main(){
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    T = 1;
    cin >> T;
    while(T--){
        solve();
    }
}

D - Twist the Permutation

题意

从前往后选择当前的数放到最前面,然后这个数前面的其他的数后移

问对于每一位需要操作几次才能使得1,2,3,...,n变为给定的数列

题解

如果你模拟过一遍样例你就会发现

根本没有头绪

有句话说的好,正难则反

我们发现,当前位操作之后不会影响后面的数变化,那么我们假设我们的数列一开始就是原数列,然后变为1,2,3,..,n,那么我们不如把每一位都让他是答案,从后往前来进行操作,那么我们就模拟这个过程就好了

Code

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <map>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#include <sstream>
#include <unordered_map>
#define ll long long
#define ull unsigned long long
#define re return
#define pb push_back
#define Endl "\n"
#define endl "\n"
#define x first
#define y second
#define all(x) (x).begin(),(x).end()

using namespace std;

typedef pair<int, int> PII;

const int N = 1e5 + 10;
const int M = 1e5 + 10;
const int mod = 1000000007;
const int INF = 0x3f3f3f3f;

int dx[4] = {-1,0,1,0};
int dy[4] = {0,1,0,-1};

int T;
int n;
int b[N];
int tmp[N];

void solve(){
    cin >> n;
    // vector<int> v;
    for (int i = 1; i <= n; i++){
        cin >> b[i];
        // v.pb(b[i]);
    }
    vector<int> res;
    for (int i = n; i >= 1; i --){
        int cnt = 0;
        int j;
        for (j = 1; j <= i; j++){
            if(b[j] == i){
                break;
            }
        }
        res.pb(j % i);
        // cout << i - j << ' ' << j << Endl;
        for (int k = j + 1; k <= i; k++){
            tmp[++cnt] = b[k];
        }
        for (int k = 1; k < j; k++){
            tmp[++cnt] = b[k];
        }

        memcpy(b, tmp, sizeof(b));
    }
    reverse(all(res));
    for(auto i : res){
        cout << i << ' ';
    }
    cout << endl;
}

int main(){
    // ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    T = 1;
    cin >> T;
    while(T--){
        solve();
    }
}

G是一个次短路板题,改一下进阶指南的代码就能过

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值