题解:AT_cf17_final_e Combination Lock
Rainesxiao · · 题解
思路
本文中所有运算都是在模
首先,对于回文串,可以将左半部分对应位置的值减去右半部分的值,同时将区间操作右边的部分压到左边,这样问题就变成一个序列,有
可以想到差分,由于一加一减和不变,因而可以想到用并查集将
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
const int N=1e5+5,mod=26;
char s[N];
int val[N],T,n,m,tot,b[N<<1],del[N],tt[N];
pii a[N];
int fa[N*30],siz[N*30],ff[N*30];
int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
void merge(int x,int y){
x=find(x),y=find(y);
if(x!=y) fa[y]=x,siz[x]=(siz[x]+siz[y])%mod;
}
vector<pii> t[N];
void solve(){
tot=0;
cin>>s>>m;n=strlen(s);
for(int i=1;i<=n;i++) val[i]=s[i-1]-'a';
for(int i=1;i<=n/2;i++) val[i]=(val[i]+mod-val[n-i+1])%mod;val[n/2+1]=0;
for(int i=1;i<=n/2+1;i++) del[i]=(val[i]+mod-val[i-1])%mod;
for(int i=1;i<=m;i++){
int l,r;cin>>l>>r;
if((n&1)&&l==n/2+1) l++;
if((n&1)&&r==n/2+1) r--;
if(l>r) continue;
if(r<=n/2) a[++tot]={l,r};
else if(l>n/2) a[++tot]={n-r+1,n-l+1};
else if(l<n-r+1) a[++tot]={l,n-r};
else if(l>n-r+1) a[++tot]={n-r+1,l-1};
}
sort(a+1,a+tot+1),tot=unique(a+1,a+tot+1)-a-1;
for(int i=1;i<=n/2+1;i++) fa[i]=i,siz[i]=del[i];
for(int i=1;i<=tot;i++){
merge(a[i].first,a[i].second+1);
}
for(int i=1;i<=n/2+1;i++) if(siz[find(i)]){cout<<"NO\n";return;}
cout<<"YES\n";
}
signed main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
solve();
return 0;
}