题目大意:假设有两段完全相同的长为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;
}