NC223414. 科学幻想
描述
2:询问凶真,区间的字符串与区间的字符串是否勉强相等。
凶真认为,若两个字符串长度相等,且两个字符串对应位置上最多有一个位置的字符不同,则这两个字符串勉强相等。例如:aaa与aaa、aab、aba、baa这四个字符串均勉强相等,但是aaa与abb不能算勉强相等。
凶真知道字符串中的字符从始至终只有小写字母这个类型,请问凶真对每个2类型指令的回答。
输入描述
第一行两个正整数,,其中,。
第二行一个长度为的字符串。
接下来行,每行第一个整数表示指令类型,。
若为,输入正整数与字符,其中。
若为,输入正整数,,,,其中,。
输出描述
输出凶真对每个2类型指令的回答,若勉强相等输出YES,否则输出NO。
示例1
输入:
6 3 abcaec 2 1 3 4 6 1 3 z 2 1 3 4 6
输出:
YES NO
C++ 解法, 执行用时: 121ms, 内存消耗: 2420K, 提交时间: 2021-07-21 22:57:11
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef unsigned long long ull; const int N=1e5+10; const int maxn=1e5; ull H[N]; ull t[N]; char s[N]; inline int lowbit(int x){ return x&-x; } ull getsum(int x){ ull res=0; for(int i=x;i>0;i-=lowbit(i)){ res+=t[i]; } return res; } void add(int x,ull y){ for(int i=x;i<=maxn;i+=lowbit(i)){ t[i]+=y; } } bool check(int l1,int r1,int l2,int r2){ ull res1=getsum(r1)-getsum(l1-1); ull res2=getsum(r2)-getsum(l2-1); if(l1<=l2){ return res1*H[l2-l1]==res2; } else{ return res2*H[l1-l2]==res1; } } int main() { int seed=31; H[0]=1; for(int i=1;i<=100000;i++){ H[i]=H[i-1]*seed; } int n,m; scanf("%d%d",&n,&m); scanf("%s",s+1); for(int i=1;i<=n;i++){ add(i,(s[i]-'a')*H[i]); } for(int i=1;i<=m;i++){ int op; scanf("%d",&op); if(op==1){ int x; char c[3]; scanf("%d%s",&x,c); add(x,-(s[x]-'a')*H[x]); s[x]=c[0]; add(x,(s[x]-'a')*H[x]); } else{ int l1,r1,l2,r2; scanf("%d%d%d%d",&l1,&r1,&l2,&r2); if(r1-l1!=r2-l2){ printf("NO\n"); continue; } int l=1,r=r1-l1+1,mid; while(l<=r){ mid=(l+r)>>1; if(check(l1,l1+mid-1,l2,l2+mid-1)){ l=mid+1; } else r=mid-1; } if(l==r1-l1+2){ printf("YES\n"); continue; } int pos=r+1; if(check(l1+pos,r1,l2+pos,r2)){ printf("YES\n"); } else printf("NO\n"); } } return 0; }