题解:AT_cf17_final_e Combination Lock
zhangwenyuxuan · · 题解
注意,以下的所有计算都在模
首先可以把字符串转化成
显然可以考虑查分,设
观察发现,一个操作相当于规定
但只连这些边,限制依然不好处理,考虑把每个点和它在回文串中对应的点也连边。此时,每个连通块的和为
现在,一个连通块中有若干对点,每对点中至少一个可以任意分配,先任选一对,通过改变其中一个大小,使得它们和为
综上所述,每个连通块中所有数的和为
:::info[参考代码]
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int t,n,sz,a[N],b[N],fa[N],sum[N];
string s;
int find(int x){
return fa[x]==x?x:fa[x]=find(fa[x]);
}
void merge(int x,int y){
fa[find(x)]=find(y);
}
int main(){
cin.tie(0);
cout.tie(0);
ios::sync_with_stdio(false);
cin>>s>>n;
sz=s.size();
for(int i=1;i<=sz;i++){
a[i]=s[i-1]-'a';
}
a[sz+1]=0;
for(int i=0;i<=sz;i++){
b[i]=a[i+1]-a[i];
fa[i]=i;
sum[i]=0;
}
for(int i=0;i*2<=sz;i++){
merge(i,sz-i);
}
for(int i=1;i<=n;i++){
int l,r;
cin>>l>>r;
merge(l-1,r);
}
for(int i=0;i<=sz;i++){
sum[find(i)]+=b[i];
}
int ans=1;
for(int i=0;i<=sz;i++){
if(sum[i]%26!=0){
ans=0;
}
}
cout<<(ans?"YES\n":"NO\n");
return 0;
}
:::