Codeforces Round #807 div2 CD

这篇博客探讨了两种字符串操作问题。第一题涉及对字符串进行多次复制操作,并根据给定的范围更新字符串,然后回答查询关于最终字符串的特定位置字符。解决方案通过递归和前缀和来模拟过程。第二题则关注于通过翻转01串中连续1的子串,判断能否将一个串转换成另一个串,并求最小操作次数。关键在于分析全段1的数量和位置变化。
摘要由CSDN通过智能技术生成

C

题意

现有一个字符串 ,执行若干 copy 操作:将 copy到 的字符添加到末尾。

进行 q次询问,每次询问需要回答最终结果串 s的某个位置的字符。

找下标,然后再通过下标输出
从最后一段一直往前模拟递推字符在启示串中的位置即可
递归

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2*1e5+10;
ll sum[N],l[N],r[N];
char s[N];
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n,c,q;
        cin>>n>>c>>q;
 
        cin>>s+1;
        sum[0]=n;
        for(int i=1;i<=c;i++)
        {
            cin>>l[i]>>r[i];
            sum[i]=sum[i-1]+r[i]-l[i]+1;
        }
 
 
        for(int i=0;i<q;i++)
        {
            ll x;
            cin>>x;
            for(int j=c;j>=1;j--)//有递归那感觉
            {
                if(x>sum[j-1]&&x<=sum[j])//一直向前搜索,直到找到最初始的l,r
                x=l[j]+x-sum[j-1]-1;//x-sum[j-1]是x在第j次复制的串中的第几个位置
     //如abcdcd中的第二个d下标是6,x=6,而sum[j-1]=4,6-4=2,
     //所以这个d是第j次复制的串的第二个元素
     //然后还有l[j]是第j次复制时的最左边的下标,这里的l[j]就为3,
     //(从abcdcd中第一个c开始,然后长度为2,因为是包括c本身得所以要-1)
     //最终这个式子得到6-4+3-1=4,4是小于等于sum[1]的,所以再执行一次,
     //x=1+4-0-1=4,for循环执行完了,直接cout<<s[4]<<endl;
     //再举一个例
     //abcdcdcdc 找最后一个c
     //123456789
    //   1 1   1
                
            }
            cout<<s[x]<<endl;
        }
    }
    return 0;
}

D

题意

给出两个01串s和t,每次操作可以把s中两个不同字符中间的字符翻转,问能否通过这种操作使得变为t,如果可以,至少需要多少步?

分析

这个操作的本质其实就是,把连续的一段1,变长或者变短,还可以移动位置,但是不可以与其他1的全段相连,所以这种操作不会改变序列中全段的数量.

比如01001可以变成00101,01101等等.首先我们需要特判一下字符串起始和最后的位置字符是否相同,因为这两个位置字符是永远无法修改的.

然后我们只需要check两个串中的1全串是否数量相等即可.

那最小步数怎么算呢?比如把01100变成00110,我们发现最少操作步数其实就是全段左右端点变化的距离之和,累加起来就是答案.

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10,INF=0x3f3f3f3f;
char s1[N],s2[N];
int main()
{
    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(0);

    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n>>s1+1>>s2+1;
        if(s1[1]!=s2[1]||s1[n]!=s2[n]){
            cout<<-1<<endl;
            continue;
        }
        vector<pair<int,int> >v1,v2;
        for(int i=1;i<=n;i++){
            if(s1[i]=='0')continue;
            int j=i;
            while(j+1<=n&&s1[j+1]=='1')j++;
            v1.push_back({i,j});
            i=j;
        }
        for(int i=1;i<=n;i++)
        {
            if(s2[i]=='0')continue;
            int j=i;
            while(j+1<=n&&s2[j+1]=='1')j++;
            v2.push_back({i,j});
            i=j;
        }
        if(v1.size()!=v2.size()){
            cout<<-1<<endl;
            continue;
        }
        ll res=0;
        for(int i=0;i<v1.size();i++){
            auto[l1,r1]=v1[i];
            auto[l2,r2]=v2[i];
            res+=abs(l2-l1)+abs(r2-r1);
        }
        cout<<res<<endl;
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值