欢迎您访问365答案网,请分享给你的朋友!
生活常识 学习资料

CodeforcesRound#770F.FibonacciAdditions(构造+差分)

时间:2023-05-27
题目

长为n(n<=3e5)的序列a、b,模数mod(1<=mod<=1e9+7)

两个序列有初值,0<=ai,bi

q(q<=3e5)次操作,每次给一个a或b的区间加上一个斐波那契数列,

此处,fib[1]=fib[2]=1%mod,fib[i]=(fib[i-1]+fib[i-2])%mod

A l r,对a[l]加fib[1]%mod,...,对a[r]加fib[r-l+1]%mod

B l r,对b[l]加fib[1]%mod,...,对b[r]加fib[r-l+1]%mod

每次操作后,询问两个序列是否在模mod意义下完全相同,相同输出YES,否则输出NO

思路来源

Codeforces Round #770 (Div、2) F(构造/差分) - 知乎

题解

首先,令a[i]=a[i]-b[i],

这样对a序列/b序列加fib序列,就变成对a序列加/减fib序列

然后,构造长为n+2的新数组c[i]=a[i]-a[i-1]-a[i-2],

这样,对于一段区间加/减fib数列,

只有c[l]、c[r+1]、c[r+2]三个值需要改变

维护c数组的0的个数,若没有非0的差分值,即说明二者相同

tips:这里为了避免下标越界的判断,把[1,n]挪到了[2,n+1]

心得

差分不止能维护相邻项差分QAQ

关注改变量与不变量,

可以将差分序列扩展成构造任意形如fib的递推式

代码

#includeusing namespace std;const int N=3e5+10;int n,q,v,mod,a[N],b[N],fib[N],l,r,zero;char s[5];void cal(int pos,int v){ zero-=(b[pos]!=0); b[pos]=(b[pos]+v)%mod; zero+=(b[pos]!=0);}int main(){ scanf("%d%d%d",&n,&q,&mod); fib[1]=1; for(int i=2;i<=n+1;++i){ fib[i]=(fib[i-1]+fib[i-2])%mod; scanf("%d",&a[i]); } for(int i=2;i<=n+1;++i){ scanf("%d",&v); a[i]=(a[i]-v)%mod; b[i]=((a[i]-a[i-1])%mod-a[i-2])%mod; zero+=(b[i]!=0); } for(int i=n+2;i<=n+3;++i){ b[i]=((a[i]-a[i-1])%mod-a[i-2])%mod; zero+=(b[i]!=0); } while(q--){ scanf("%s%d%d",s,&l,&r); l++;r++; int sg=(s[0]=='A'?1:-1); cal(l,sg); cal(r+1,-sg*(fib[r-l]+fib[r-l+1])%mod); cal(r+2,-sg*fib[r-l+1]); puts(!zero?"YES":"NO"); } return 0;}

Copyright © 2016-2020 www.365daan.com All Rights Reserved. 365答案网 版权所有 备案号:

部分内容来自互联网,版权归原作者所有,如有冒犯请联系我们,我们将在三个工作时内妥善处理。