CF Gym 101615I Long Long String【模拟】

博客探讨了对两个长度为10^10的相同DNA片段进行添加和删除操作后是否仍相等的问题。解析指出,添加操作不影响序列相对位置,而删除操作会影响后续片段。解决方案涉及维护新添加和删除片段的集合,通过更新片段位置来判断最终序列是否一致。
摘要由CSDN通过智能技术生成

题目大意:假设有两段完全相同的长为10^10的DNA片段,现在对其有两组操作,每组操作包含两种操作,一个是删除当前下标为x的片段,一个是在下标为x的片段前添加一个新片段,问两组操作过后两个DNA片段还相等吗,如果相等则输出0,不等则输出1。

解析:如果只看添加操作,可以看到根据一个个添加的坐标可以确定每个添加的片段的坐标更新情况,对原队列的相对位置不产生影响;那么在加上删除操作之后,可以删除新添加的片段,也可以删除原队列的片段,每个删除操作都会对后面的队列产生影响,对前面的无影响。

具体解法:那么就可以维护两个集合,一个集合是新添加的片段,维护所有新添加的片段的位置,另一个集合是删除的片段在最原始序列的位置;
对于每一个添加操作,其对原队列不产生影响,更新其在最新的序列中的位置,具体的就是对于在新添加的片段后的之前添加的片段,其坐标加1;
删除操作则相对复杂一点,首先能想到的是删除操作会更改新添加片段在序列中的坐标,所以要维护一下新片段集合,然后要确定删除的是新添加的片段还是原始片段,因为新片段集合维护的是当前位置,所以很好判断出是删除新添加的片段还是原始片段,如果是新添加的片段,就把新片段从新添加片段中删除,如果是原始片段,则要确定要删除的片段在原始片段中的坐标,对原始片段坐标产生影响的有两方面,一方面是新添加的片段,输入的坐标前面有多少新添加的片段,输入的坐标就要减去多少,还有就是之前已经删除的坐标前面有多少删除的坐标,输入的坐标就要加多少,这样就能确定要删除的坐标在原始片段中的位置。

做完所有操作之后,将集合比较一下,如果新添加的片段位置元素都一样,删除原始队列的元素都一样,那么两组操作之后得到的结果是完全相同的

下面是我的AC代码:
(为了维护方便,删除片段在原始队列中的位置我是按照从小到大维护的,在做完所有操作之后新添加队列我排了一下序,以便比较方便,也可在维护过程中就排好序,方法和删除片段差不多,同时要注意执行删除之后下标的变化)

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

vector<ll>dl[2];
vector<pair<ll,char> >il[2];

void deal(int num){
    char temp;
    while(cin >> temp&&temp!='E'){
        if(temp == 'D'){
            ll index;
            cin >> index;
            ll l = il[num].size();
            ll inx = index;
            ll flag = -1;
            for(int i = 0;i < l;i++){
                if(index == il[num][i].first){
                    flag = i;
                }
                else if(index > il[num][i].first){
                    inx--;
                }
                else{
                    il[num][i].first--;
                }
            }
            if(flag==-1){
                l = dl[num].size();
                if(l == 0){
                    dl[num].push_back(inx);
                }
                for(int i = 0;i < l;i++){
                    if(dl[num][i]<=inx){
                        inx++;
                    }
                    else{
                        dl[num].insert(dl[num].begin()+i,inx);
                        break;
                    }
                }
                if(l == dl[num].size()){
                    dl[num].push_back(inx);
                }
            }
            else{
                il[num].erase(il[num].begin()+flag);
            }
        }
        else{
            char tmp;
            ll index;
            cin >> index >> tmp;
            int l = il[num].size();
            for(int i = 0;i < l;i++){
                if(il[num][i].first >= index){
                    il[num][i].first++;
                }
            }
            il[num].push_back(make_pair(index,tmp));
        }
    }
}

int main()
{
    deal(0);
    deal(1);
    sort(il[0].begin(),il[0].end());
    sort(il[1].begin(),il[1].end());
    if(dl[0].size()==dl[1].size()){
        if(il[0].size()==il[1].size()){
            int l = dl[0].size();
            bool flag = true;
            for(int i = 0;i < l;i++){
                //cout << i << '\n' << dl[0][i] << ' ' << dl[1][i] << '\n';
                if(dl[0][i]!=dl[1][i]){
                    flag = false;
                    break;
                }
            }
            if(flag){
                l = il[0].size();
                for(int i = 0;i < l;i++){
                    if(il[0][i]!=il[1][i]){
                        flag = false;
                        break;
                    }
                }
                if(flag){
                    cout << 0 << '\n';
                }
                else{
                    cout << 1 << '\n';
                }
            }
            else{
                cout << 1 << '\n';
            }
        }
        else{
            cout << 1 << '\n';
        }
    }
    else{
        cout << 1 << '\n';
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值