专栏文章
题解:P8521 [IOI 2021] 修改 DNA
P8521题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mipbtcto
- 此快照首次捕获于
- 2025/12/03 09:26 3 个月前
- 此快照最后确认于
- 2025/12/03 09:26 3 个月前
先判断什么时候无解,显然是 中某种字符出现次数和 中某种字符出现次数不相等,这样才会出现无解的情况。这个直接用前缀和做即可。
考虑将 和 每一位配对起来。如果一个位置 的字符相等则不用管它;如果存在两个位置配对起来的结果正好相反,则这两个位置可以直接抵消,对答案的贡献为 。
将上述两种情况的点删去,剩下的序列只能是这两种情况:
或者:
我们注意到,这样对答案的贡献是 ,直接加进去就行了。
代码:
CPP#include<bits/stdc++.h>
#include<bits/extc++.h>
#define ll long long
using namespace std;
ll read(){
ll x=0,f=1;char ch=getchar_unlocked();
while(ch<'0'||'9'<ch){if(ch=='-')f=-1;ch=getchar_unlocked();}
while('0'<=ch&&ch<='9'){x=x*10+ch-'0';ch=getchar_unlocked();}
return f*x;
}
const int N = 1e5+5;
int n,q,s[N][5][5],sa[N][5],sb[N][5],kk[305],cp[5][5];
void init(string a,string b){n=a.size();
memset(kk,0,sizeof(kk));memset(s,0,sizeof(s));
memset(sa,0,sizeof(sa));memset(sb,0,sizeof(sb));
kk['A']=0,kk['T']=1,kk['C']=2;a=" "+a,b=" "+b;
for(int i=1;i<=n;i++){
for(int x=0;x<3;x++){
sa[i][x]=sa[i-1][x];sb[i][x]=sb[i-1][x];
for(int y=0;y<3;y++)s[i][x][y]=s[i-1][x][y];
}sa[i][kk[a[i]]]++,sb[i][kk[b[i]]]++;
s[i][kk[a[i]]][kk[b[i]]]++;
}
// for(int x=0;x<3;x++){
// for(int i=0;i<n;i++)printf("%d ",sa[i][x]);puts("");
// for(int i=0;i<n;i++)printf("%d ",sb[i][x]);puts("");puts("");
// }
}
int get_distance(int l,int r){int ans=0;l++,r++;
for(int x=0;x<3;x++)for(int y=0;y<3;y++)cp[x][y]=0;
for(int x=0;x<3;x++){
// printf("%d %d %d\n",x,sa[r][x]-sa[l-1][x],sb[r][x]-sb[l-1][x]);
if(sa[r][x]-sa[l-1][x]!=sb[r][x]-sb[l-1][x])return -1;
}
for(int x=0;x<3;x++)for(int y=0;y<3;y++)cp[x][y]=s[r][x][y]-s[l-1][x][y];
for(int x=0;x<3;x++)for(int y=x+1;y<3;y++){
int mm=min(cp[x][y],cp[y][x]);ans+=mm,cp[x][y]-=mm,cp[y][x]-=mm;
}int mx=0;for(int x=0;x<3;x++)for(int y=x+1;y<3;y++)if(cp[x][y]>mx)mx=cp[x][y];
ans+=mx*2;return ans;
}
#ifndef ONLINE_JUDGE
int main(){
cin>>n>>q;string a,b;
cin>>a>>b;init(a,b);
while(q--){
int l,r;cin>>l>>r;
cout<<get_distance(l,r)<<endl;
}
return 0;
}
#endif
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...