給一個只有1和2的序列,每次詢問有沒有一個子串的和爲xios
( 1≤n,m≤1 000 000 )kkk ( 1≤k≤2 000 000 )spa
我以爲是道好題。code
主要是證實一個性質:假若有一個字串的和爲偶(奇)數,那麼小於這個偶(奇)數的全部偶(奇)數必定等於這個串的某個字串的和。blog
咱們考慮這個串的邊界l,rci
假設l==1,r==1那麼l++,r--,和能夠減2string
假設l==2,r==1那麼l++,和能夠減2;it
假設l==1,r==2那麼r--,和能夠減2;io
假設l==2,r==2那麼l++或r--和能夠減2;class
因此咱們找到能夠用一個串表示的最大偶(奇)數而後一直縮小這個區間就行。stream
1 #include<iostream> 2 #include<cstring> 3 #include<cmath> 4 #include<cstdio> 5 #include<algorithm> 6 using namespace std; 7 const int N=1000100; 8 const int M=2000100; 9 char s[M]; 10 int n,m,a[N],sum,head,tail,l,r,ll[M],rl[M]; 11 int main(){ 12 scanf("%d%d",&n,&m); 13 cin>>s; 14 int len=strlen(s); 15 for(int i=0;i<len;i++){ 16 if(s[i]=='W')a[i+1]=1; 17 else a[i+1]=2; 18 } 19 for(int i=1;i<=n;i++) 20 sum+=a[i]; 21 head=1; 22 tail=n; 23 while(a[head]!=1&&head<=n)head++; 24 head++; 25 while(a[tail]!=1&&tail>=1)tail--; 26 tail--; 27 l=1;r=n; 28 while(l<=r){ 29 // cout<<sum<<" "<<l<<" "<<r<<endl; 30 rl[sum]=r;ll[sum]=l; 31 if(a[l]==1&&a[r]==1){ 32 l++;r--;sum-=2; 33 } 34 else if(a[l]==2){ 35 l++;sum-=2; 36 } 37 else{ 38 r--; 39 sum-=2; 40 } 41 } 42 sum=0; 43 if(head<=n||tail>=1){ 44 if(head-1<n-tail){ 45 l=head; 46 r=n; 47 for(int i=head;i<=n;i++) 48 sum+=a[i]; 49 } 50 else{ 51 l=1;r=tail; 52 for(int i=1;i<=tail;i++) 53 sum+=a[i]; 54 } 55 // cout<<sum<<endl; 56 while(l<=r){ 57 rl[sum]=r;ll[sum]=l; 58 if(a[l]==1&&a[r]==1){ 59 l++;r--;sum-=2; 60 } 61 else if(a[l]==2){ 62 l++;sum-=2; 63 } 64 else{ 65 r--; 66 sum-=2; 67 } 68 } 69 } 70 for(int i=1;i<=m;i++){ 71 int k; 72 scanf("%d",&k); 73 if(ll[k]==0&&rl[k]==0)printf("NIE\n"); 74 else printf("%d %d\n",ll[k],rl[k]); 75 } 76 return 0; 77 }