Codeforces Round #770 (Div. 2) F. Fibonacci Additions(构造+差分)

题目

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

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

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的递推式

代码

#include<bits/stdc++.h>
using 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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Code92007

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值