洛谷月赛 LGR-099 div.2 A-B题解

本文解析了洛谷月赛div.2中的两道题目,包括字符串合并问题及Alice和Bob的游戏策略。针对字符串合并问题,提出了枚举开头并查找相同前缀的方法;对于游戏策略问题,则通过分析操作的影响来确定最优解。

洛谷月赛 LGR-099 div.2 A-B题解

前两天没事刷了下洛谷月赛div2,发现打卡题难度都提高了些,在出题人的帮助下AC了前两题。

题目

  1. Easy Strings Merging
    在这里插入图片描述
思路(最容易想到的)

这题很容易就能想到,字符串头只能为0或1。所以我们可以枚举开头0、1,然后查找每一个字符串是否有相同的前缀,如果相同则加入,找不到则换一个。于是,我们可以将每个字符串存进vector中,遍历到符合的就加入,如果此时字符串为空,那么size–,当size==0时说明每个字符串都处理结束了。

注意

在vector中eraser的时间复杂度很大,如果使用会导致后面的测试点TLE(在出题人帮助下发现的)。所以在当前字符串处理结束后,不能直接vector.eraser掉。

#include<bits/stdc++.h>
#define io_opt ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define INF 0x3f3f3f3f
using namespace std;

typedef long long ll;
typedef pair<int, int> PII;
const int N = 1e6 + 10;

int n, ans;
int check(string);
int solve(vector<string>, string);

int main() {
    io_opt;
    cin >> n;
    vector<string> vtr(n);
    for (int i = 0; i < n; i++) cin >> vtr[i];
    if (n == 1) {
        ans = check(vtr[0]);
    }
    else {
        ans = max(solve(vtr, "0"), solve(vtr, "1"));
    }
    cout << ans << endl;
    return 0;
}
int solve(vector<string> vtr, string str) {
    int size = n;
    while (size) {
        int sta = 0, en = vtr.size();
        for (; sta < en; sta++) {
            if(vtr[sta].empty()) continue;
            int k = 0;
            while (vtr[sta][k] == str.back()) k++;
            str += vtr[sta].substr(0, k);
            vtr[sta].erase(0, k);
            if (vtr[sta].empty()) size--;
        }
        if (sta == en) {
            for(sta=0;sta<en;sta++){
                if(!vtr[sta].empty()){
                    str += vtr[sta][0];
                    vtr[sta].erase(0, 1);
                    if (vtr[sta].empty()) size--;
                }
            }            
        }
    }
    return check(str.erase(0, 1));
}
int check(string str) {
    int res = 0;
    for (int i = 0; i < str.size(); i++) {
        if (str[i] == str[i + 1]) res++;
    }
    return res;
}
  1. Alice and Bob are playing a Normal Game
    在这里插入图片描述
思路

Alice和Bob可以对数列在头部或尾部插入一个范围在[-xi,xi]的数字。数组得分由每个元素计算得到,奇数位置加,偶数位置减。所以我们可以得知,若在头部插入一个数字,那么之前数组的每一个元素位置都会向后移动,即为奇偶性相反,那么得分也会相反,若在尾部插入一个数字那么对之前得分没有影响。所以可以理解,每一步操作都可以使数组的变正变负,并且可以加入一个范围在[-xi,xi]的数字。所以最后一部操作的人可以使数组向他期望的方向变换,例如:Alice希望得分大,如果上一步得分为负数,可以在头部插入一个数字使它变为正数。所以题目中的都采取最优操作,即为最后操作的人每次都使得分绝对值最大,另一个人每次都让得分绝对值最小,这样最后操作的人能使得分最大,另一个人能使损失最小。

注意
  1. 希望绝对值变小要判断ans和xi大小关系,如果ans <= xi 那么可以变成0,而不是单纯的ans - xi
#include<bits/stdc++.h>
#define io_opt ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define INF 0x3f3f3f3f
#define rg register
using namespace std;

typedef long long ll;
typedef pair<int,int> PII;
const int N = 1e6 + 10;

int n,k,t,x;
int main() {
    io_opt;
    ll ans = 0;
    cin >> n >> k;
    for(int i=1;i<=n;i++){
        cin >> t;
        ans += (i % 2 ? t : -t);
    }
    if(ans < 0) ans = -ans;
    int op = k % 2; //记录最后一个人
    while(k--){
        cin >> x; 
        ans = (k & 1) ? ((ans > x )?(ans - x): 0):(ans + x);
    }
    if(!op) ans = -abs(ans);
    cout << ans << endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值