[权值线段树] Jzoj P4417 神奇的字符串
题解
- 显然,直接用字符串匹配是不可做的。
- 考虑把(A*i+B)%N相同的分成一类,它们其实都是一段连续的区间
- 它们对应的开头也是有序的c[j-i]=c[j]-a*i,所以开头也是有序的
- 那么就形成了很多个区间,这个点被多少个区间所覆盖也就是说他和s串有多少个字符是相同的
- 答案就是用总数-被区间覆盖的个数
代码
1 #include <cstdio> 2 #include <iostream> 3 #include <cstring> 4 using namespace std; 5 const int M=100010; 6 int n,a,b,p,m,c[M],tot=1,Q,x; 7 char ch[10]; 8 struct node{ int l,r,v,lazy; }tree[10000005]; 9 struct edge{ int l,r; }; 10 edge work(int x,int y) 11 { 12 int l,r; 13 if (y==0) l=p,r=n-1; else l=0,r=p-1; 14 l=((l-a*x)%n+n)%n,r=((r-a*x)%n+n)%n; 15 return (edge){l,r}; 16 } 17 void Lazy(int x) 18 { 19 tree[tree[x].l].lazy+=tree[x].lazy,tree[tree[x].l].v+=tree[x].lazy; 20 tree[tree[x].r].lazy+=tree[x].lazy,tree[tree[x].r].v+=tree[x].lazy; 21 tree[x].lazy=0; 22 } 23 void change(int d,int l,int r,int L,int R,int k) 24 { 25 if (l==L&&r==R) { tree[d].v+=k,tree[d].lazy+=k; return; } 26 int mid=l+r>>1; 27 if (!tree[d].l) tree[d].l=++tot; if (!tree[d].r) tree[d].r=++tot; 28 Lazy(d); 29 if (R<=mid) change(tree[d].l,l,mid,L,R,k); else if (L>mid) change(tree[d].r,mid+1,r,L,R,k); 30 else change(tree[d].l,l,mid,L,mid,k),change(tree[d].r,mid+1,r,mid+1,R,k); 31 } 32 int Query(int d,int l,int r,int k) 33 { 34 if (l==r) return tree[d].v; 35 int mid=l+r>>1; 36 if (!tree[d].l) tree[d].l=++tot; if (!tree[d].r) tree[d].r=++tot; 37 Lazy(d); 38 return (k<=mid)?Query(tree[d].l,l,mid,k):Query(tree[d].r,mid+1,r,k); 39 } 40 int main() 41 { 42 scanf("%d%d%d%d%d",&n,&a,&b,&p,&m); 43 for (int i=1;i<=m;i++) 44 { 45 char ch=' '; while (ch!='0'&&ch!='1') ch=getchar(); 46 c[i]=ch-48; edge e=work(i-1,c[i]); 47 if (e.l<=e.r) change(1,0,n-1,e.l,e.r,1); else change(1,0,n-1,0,e.r,1),change(1,0,n-1,e.l,n-1,1); 48 } 49 scanf("%d\n",&Q); 50 while (Q--) 51 { 52 scanf("%s%d\n",ch,&x); 53 if (ch[0]=='Q') printf("%d\n",Query(1,0,n-1,(x*a+b)%n)); 54 else 55 { 56 x++; edge e=work(x-1,c[x]); 57 if (e.l<=e.r) change(1,0,n-1,e.l,e.r,-1); else change(1,0,n-1,0,e.r,-1),change(1,0,n-1,e.l,n-1,-1); 58 c[x]=(c[x]+1)%2,e=work(x-1,c[x]); 59 if (e.l<=e.r) change(1,0,n-1,e.l,e.r,1); else change(1,0,n-1,0,e.r,1),change(1,0,n-1,e.l,n-1,1); 60 } 61 } 62 }