Codeforces Round #704 (Div. 2) A~C题解

写在前边

链接:Codeforces Round #704 (Div. 2)
D就不补了,大fst场。

A. Three swimmers

链接:A题链接

题目大意:

给定三个游泳者的到达岸边的周期,a,b,c,而你到达岸边的时间为p,现在问你到达岸边后最少需要多少时间能遇到一名游泳者。

思路

老套路题了,公式:

res=min(paa,pbb,pcc)p

注意,写代码的时候(p+a1)/aaa(p+a1)/a获得的结果也不一样,前一种正确。

代码:

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <unordered_map>

using namespace std;

#define Inf 0x3f3f3f3f
#define PII pair<int, int>
#define P2LL pair<long long, long long>
#define endl '\n'

typedef long long LL;
typedef unsigned long long ULL;
typedef vector<long long> VLL;
typedef vector<int> VI;

void solve() {
    LL p, a, b, c;
    cin >> p >> a >> b >> c;
    LL a1, b1, c1;
    a = (p + a - 1) / a * a;
    b = (p + b - 1) / b * b;
    c = (p + c - 1) / c * c;

    cout << min(a, min(b, c)) - p << endl;
}

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

    return 0;
} 

B. Card Deck

链接:B题链接

题目大意:

一副扑克盘,从上往下拿,截止点作为新牌的起点,会形成一种新的顺序,使得这种顺序权值最大,计算权值公式:

i=1nnnipi

思路

把公式展开后就得出让新的牌须变成字典序最大即可,那么我们就每一次以剩余的最大数作为截止点拿牌,形成新的顺序,一开始就想到这种方法了,但是复杂度想成了O(n2)没敢做,于是看题解后,做的也是这种方法,于是想了一下复杂度并不是O(n2),最坏是是O(n+n)

代码:

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <map>
#include <cstring>
#include <set>

//#pragma GCC optimize(2)
//#pragma GCC optimize(3,"Ofast","inline")

using namespace std;

#define Inf 0x3f3f3f3f
#define PII pair<int, int>
#define P2LL pair<long long, long long>
#define endl '\n'

typedef long long LL;
typedef unsigned long long ULL;
typedef vector<long long> VLL;
typedef vector<int> VI;

const int Mod = 10000007;

LL gcd(LL a, LL b) {
    return b ? gcd(b, a % b) : a;
}

const int N = 1e5 + 10;
int a[N];

void solve() {
    int n;
    scanf("%d", &n);
    
    for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
    
    set<int> st;
    vector<int> rem;
    for (int i = 1; i <= n; i++) st.insert(i);

    int maxn = n;
    for (int i = n; i >= 1; i--) {
        rem.push_back(a[i]);
        st.erase(a[i]);
        if (a[i] == maxn) {
            reverse(rem.begin(), rem.end());
            for (auto &it : rem) cout << it << " ";
            rem.clear();
            if (st.size()) maxn = *(--st.end());
        }
    }
    cout << endl;
}

int main()
{
    //ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
    int t;
    scanf("%d", &t); 
    while (t--) {
        solve();
    }
    return 0;
}

C. Maximum width

链接:C题链接

题目大意:

给定一个长度分别为nm的字符串st,同时可以得到一个序列p1p1p2p3...n,使得spi=ti对于所有的s[1,m],让我们构造以p得到一个max1im(pi+1pi)

思路

每次做这种题都会让坐标烦,这道题仔细抠一下题意就是在s中找到一个t,并使得ts中相邻两个字母的坐标差最大,那么可以分别从前边可后边维护两个数组f,gfi表示ti在s中最左侧位置下标,gi就表示tis中最右侧位置的下边,那么答案就是max1im1(gi+1fi)

代码:

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <unordered_map>

using namespace std;

#define Inf 0x3f3f3f3f
#define PII pair<int, int>
#define P2LL pair<long long, long long>
#define endl '\n'

typedef long long LL;
typedef unsigned long long ULL;
typedef vector<long long> VLL;
typedef vector<int> VI;

const int N = 2e5 + 10;
char s[N], t[N];
int f[N], g[N];

void solve() {
    int n, m;
    scanf("%d%d", &n, &m);
    scanf("%s", s + 1);
    scanf("%s", t + 1);

    int cnt = 1;
    for (int i = 1; i <= m; i++) {
        while (s[cnt] != t[i]) cnt++;
        f[i] = cnt;
        cnt++;
    }

    cnt = n;
    for (int i = m; i >= 1; i--) {
        while (s[cnt] != t[i]) cnt--;
        g[i] = cnt;
        cnt--;
    }

    int res = 0;
    for (int i = 1; i <= m - 1; i++) res = max(res, g[i + 1] - f[i]);
    printf("%d\n", res);
}

int main()
{
    solve();
    return 0;
} 
posted @   Xxaj5  阅读(77)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示