Codeforces Round #469 (Div. 2) Solutions of A-D

29 篇文章 0 订阅
10 篇文章 0 订阅
本文解析了四道编程题目并提供了相应的AC代码,包括左右手人的礼物分配问题、拦截消息同步问题、斑马字符串划分问题以及数组跳跃问题。通过对每道题目的详细分析和高效算法的设计,帮助读者理解并掌握解决这类问题的方法。
摘要由CSDN通过智能技术生成

A. Left-handers, Right-handers and Ambidexters

水题,AC代码如下:

#include <iostream>
#include <iomanip>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <string>
#include <vector>

using namespace std;

#define FSIO  ios::sync_with_stdio(0);cin.tie(0);
#define DEBUG(a)   cout<<"DEBUG: "<<(a)<<endl;

const int MAXN = 105;
const int MOD = 1e9+7;


int main()
{
    int l, r, a;
    while(cin>>l>>r>>a)
    {
        int del = max(l,r) - min(l,r);
        if(a>=del)
        {
            a -= del;
            int res = max(l,r)*2;
            res += a/2*2;
            cout<<res<<endl;
        }
        else
        {
            cout<<(min(l,r)+a)*2<<endl;
        }

    }
    return 0;
}

B. Intercepted Message

水题,AC代码如下:

#include <iostream>
#include <iomanip>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <string>
#include <vector>

using namespace std;

#define FSIO  ios::sync_with_stdio(0);cin.tie(0);
#define DEBUG(a)   cout<<"DEBUG: "<<(a)<<endl;

const int MAXN = 100005;
const int MOD = 1e9+7;

int mes1[MAXN], mes2[MAXN];
int n, m;

void gogogo(int& p1, int& s1, int& p2, int& s2)
{
    while(s1!=s2)
    {
        if(s1<s2)   s1 += mes1[++p1];
        else    s2 += mes2[++p2];
    }
}

int main()
{
    FSIO;
    while(cin>>n>>m)
    {
        for(int i=1;i<=n;++i)   cin>>mes1[i];
        for(int i=1;i<=m;++i)   cin>>mes2[i];

        int cur1 = 1;
        int cur2 = 1;
        int cs1 = mes1[cur1];
        int cs2 = mes2[cur2];
        int res = 0;
        while(cur1<=n||cur2<=m)
        {
            if(cs1 == cs2)  { res++; cur1++; cur2++;   cs1 = mes1[cur1];  cs2 = mes2[cur2];}
            else
            {
                gogogo(cur1, cs1, cur2, cs2);
            }
        }
        cout<<res<<endl;
    }
    return 0;
}

C. Zebras

题意:定义了一种zebra串,从0开始到0结束,中间部分为0、1交替序列,如010,01010。要求划分一个01序列,若可以划分则输出,否则输出-1。

思路:使用vector存储每一个子串的长度,并且使用两个“单身汉”队列(顾名思义,即需要和0或者1匹配的)存储对应子串的下标。这样只需要遍历一遍原串即可。

AC代码如下:

#include <iostream>
#include <iomanip>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <string>
#include <vector>
#include <queue>

using namespace std;

#define FSIO  ios::sync_with_stdio(0);cin.tie(0);
#define DEBUG(a)   cout<<"DEBUG: "<<(a)<<endl;

const int MAXN = 200005;
const int MOD = 1e9+7;

string ss;
vector<int> res[MAXN];
queue<int>  bachelor0, bachelor1;
int cnt1, cnt0;
int ans;

int solve()
{
    if(ss[0]=='1')  return 0;
    while(!bachelor0.empty())    bachelor0.pop();
    while(!bachelor1.empty())    bachelor1.pop();

    for(int i=0;i<ss.length();++i)
    {
        if(ss[i]=='0')
        {
            if(bachelor1.size()==0)
            {
                ans++;
                res[ans].push_back(i);
                bachelor0.push(ans);
            }
            else
            {
                int tmp = bachelor1.front();
                res[tmp].push_back(i);
                bachelor0.push(tmp);
                bachelor1.pop();
            }
        }
        else
        {
            if(bachelor0.size()==0) return 0;
            else
            {
                int tmp = bachelor0.front();
                res[tmp].push_back(i);
                bachelor1.push(tmp);
                bachelor0.pop();
            }
        }
    }
    if(bachelor1.size()>0)  return 0;
    else    return 1;

    return 1;
}


int main()
{
    FSIO;
    while(cin>>ss)
    {
        for(int i=0;i<MAXN;++i) res[i].clear();
        ans = 0;
        if(solve())
        {
            cout<<ans<<endl;
            for(int i=1;i<=ans;++i)
            {
                cout<<res[i].size();
                for(int j=0;j<res[i].size();++j)
                    cout<<" "<<res[i][j]+1;
                cout<<endl;
            }
        }
        else    cout<<-1<<endl;
    }
    return 0;
}

D. A Leapfrog in the Array

题意:设定了一种数组操作,现在给你n和q个询问,询问某位置上数是多少。

思路:对于某数字x,若x <= (n+1)/2,那么它在数组中的位置为 2*x - 1,故最后数组中奇数位的判断使用这个公式即可。

对于x > (n+1)/2,打表发现,x位置的第t次移动为(2*(n-x)-1) * 2^t,

利用等比数列公式即可计算出经过t次移动后x的位置为 (2*x-1) - (2*(n-x) -1) * (2^(t+1) - 1)。

设第t次移动之前位置为 p_0, 移动之后位置为 p_1,那么 

p_0 = p_1 + (2*(n-x)-1) * 2^t

      = p_1 + (2*n - p_1)/2   // 代入p_1位置公式可以推出。

由此构建出递推式, p_0 = n + p_1/2 ,利用递归方法即可求解。

AC代码如下:

#include <iostream>
#include <iomanip>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <string>
#include <vector>
#include <queue>

using namespace std;

#define FSIO  ios::sync_with_stdio(0);cin.tie(0);
#define DEBUG(a)   cout<<"DEBUG: "<<(a)<<endl;

const int MAXN = 200005;
const int MOD = 1e9+7;

long long n;

long long solve(long long pos)
{
    if(pos%2)   return (pos+1ll)/2ll;
    else    return solve(n+pos/2ll);
}

int main()
{
    FSIO;
    int q;
    long long x;
    while(cin>>n>>q)
    {
        for(int i=1;i<=q;++i)
        {
            cin>>x;
            cout<<solve(x)<<endl;
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值