快来踩爆这个蒟蒻吧|

Little_corn

园龄:1年1个月粉丝:11关注:17

2024-04-24 13:07阅读: 11评论: 0推荐: 0

CF1634F Fibonacci Additions

Statement:

给出两个长度为 n 的序列 a,b,每次在 ab[l,r] 操作,一次操作将会使 [l,r] 中的数分别加上 fib[1],fib[2]...,fib[rl+1],每次操作完询问 a,b 是否在模 mod 意义下相等。

Solution:

先简化问题,令 ci=aibi,问题转化为每次操作完,ci 是否全 0.

其实这个问题可以直接上线段树解决。

但是我们考虑将区间操作转化为单点操作,有什么技巧可以实现呢? 差分!

差分的本质,其实是因为相邻项的增量有一定关系,根据关系设计出一个递推式,并且将区间转化为几个点的调整。

我们的增量 del 数组有这样的关系:del[i]=del[i1]+del[i2]。移项得到 del[i]del[i1]del[i2]=0,于是 del[i]del[i1]del[i2] 其实就是不变量。

于是我们设计差分数组 d[i]=c[i]c[i1]c[i2]

分析操作带来的影响(这里分析 A 数组):

首先对于 dl 显然需要 +f[1]dr+1 因为 cr+1 不变,所以 frl+2dr+2 同时也要 frl+1.

Code:

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 3e5 + 1145;
int n, q, mod, a[N], b[N], c[N], d[N], f[N], cnt;
void ch(int x, int ad){
if(x > n || x < 1) return;
int tmp = (d[x] + (ad % mod + mod) % mod) % mod;
if(d[x] == 0 && tmp) cnt--;
else if(d[x] != 0 && (!tmp)) cnt++;
d[x] = tmp;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin >> n >> q >> mod;
for(int i = 1; i <= n; i++) cin >> a[i];
for(int i = 1; i <= n; i++) cin >> b[i];
f[1] = f[2] = 1;
for(int i = 3; i <= n + 114; i++) f[i] = (f[i - 1] + f[i - 2]) % mod;
for(int i = 1; i <= n; i++) c[i] = (a[i] - b[i] + mod) % mod, d[i] = ((c[i] - c[i - 1] - c[max(0ll, i - 2)]) + mod) % mod, ch(i, 0), cnt += (d[i] == 0);
while(q--){
char c; int l, r; cin >> c >> l >> r;
if(c == 'A'){
ch(l, f[1]); ch(r + 1, -f[r - l + 2]); ch(r + 2, -f[r - l + 1]);
}
else{
ch(l, -f[1]); ch(r + 1, f[r - l + 2]); ch(r + 2, f[r - l + 1]);
}
if(cnt == n) cout << "YES" << "\n";
else cout << "No" << "\n";
}
return 0;
}
/*
c[i] = a[i] - b[i]
d[i] = c[i] - c[i - 1] - c[i - 2]
*/

本文作者:Little_corn

本文链接:https://www.cnblogs.com/little-corn/p/18155062

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Little_corn  阅读(11)  评论(0编辑  收藏  举报
(评论功能已被禁用)
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起