CodeForces - 316E3 Summer Homework
Discription
By the age of three Smart Beaver mastered all arithmetic operations and got this summer homework from the amazed teacher:
You are given a sequence of integers a1, a2, ..., an. Your task is to perform on it mconsecutive operations of the following type:
- For given numbers xi and vi assign value vi to element axi.
- For given numbers li and ri you've got to calculate sum , where f0 = f1 = 1 and at i ≥ 2: fi = fi - 1 + fi - 2.
- For a group of three numbers li ri di you should increase value ax by di for allx (li ≤ x ≤ ri).
Smart Beaver planned a tour around great Canadian lakes, so he asked you to help him solve the given problem.
Input
The first line contains two integers n and m (1 ≤ n, m ≤ 2·105) — the number of integers in the sequence and the number of operations, correspondingly. The second line contains n integers a1, a2, ..., an (0 ≤ ai ≤ 105). Then follow m lines, each describes an operation. Each line starts with an integer ti (1 ≤ ti ≤ 3) — the operation type:
- if ti = 1, then next follow two integers xi vi (1 ≤ xi ≤ n, 0 ≤ vi ≤ 105);
- if ti = 2, then next follow two integers li ri (1 ≤ li ≤ ri ≤ n);
- if ti = 3, then next follow three integers li ri di (1 ≤ li ≤ ri ≤ n, 0 ≤ di ≤ 105).
The input limits for scoring 30 points are (subproblem E1):
- It is guaranteed that n does not exceed 100, m does not exceed 10000 and there will be no queries of the 3-rd type.
The input limits for scoring 70 points are (subproblems E1+E2):
- It is guaranteed that there will be queries of the 1-st and 2-nd type only.
The input limits for scoring 100 points are (subproblems E1+E2+E3):
- No extra limitations.
Output
For each query print the calculated sum modulo 1000000000 (109).
Examples
5 5
1 3 1 2 4
2 1 4
2 1 5
2 2 4
1 3 10
2 1 5
12
32
8
50
5 4
1 3 1 2 4
3 1 4 1
2 2 4
1 2 10
2 1 5
12
45
最近好多 数学 + 数据结构 的题啊qwq,既要动脑子又要调代码qwq
斐波那契数列有一个非常好的性质: f[i] = f[i-1] + f[i-2]
这不是废话吗。。。。但是这个能推出来另一个东西 -> f[i] = f[k]*f[i-k] + f[k-1]*f[i-k-1] (这个式子是对于f[0]=f[1]=1的斐波那契数列而言的)。
有了这个,我们就可以随心所欲的通过 ∑f[i]*a[i+l] 和 ∑f[i+1]*a[i+l] 来构造任意 ∑f[i+d]*a[i+l] 啦(也就是程序中的Get函数)。
然后随便打打标机(别忘了下传维护之类的),随便合并合并子树,就可以A啦(但是要写一坨子qwq)
(最近压行成瘾qwq)
#include<bits/stdc++.h> #define ll long long using namespace std; const int maxn=2*1e5,ha=1e9; int f[maxn+5],F[maxn+5],a[maxn+5],le,ri,n,m,w,O; int sum[maxn*4+5][2],tag[maxn*4+5],L[maxn*4+5],A; inline void ADD(int &x,int y){ x+=y; if(x>=ha) x-=ha;} inline int add(int x,int y){ x+=y; return x>=ha?x-ha:x;} inline void init(){ f[0]=F[0]=1; for(int i=1;i<=maxn;i++) f[i]=add(f[i-1],f[i-2]),F[i]=add(f[i],F[i-1]);} inline int Get(int o,int Derta){ return Derta<2?(Derta?sum[o][1]:sum[o][0]):add(sum[o][0]*(ll)f[Derta-2]%ha,sum[o][1]*(ll)f[Derta-1]%ha);} inline void QADD(int o,int Derta){ ADD(tag[o],Derta),ADD(sum[o][0],Derta*(ll)F[L[o]-1]%ha),ADD(sum[o][1],Derta*(ll)add(F[L[o]],ha-1)%ha);} inline void pushdown(int o,int lc,int rc){ if(tag[o]){ QADD(lc,tag[o]),QADD(rc,tag[o]),tag[o]=0;}} inline void Merge(int o,int lc,int rc,int Derta){ sum[o][0]=add(sum[lc][0],Get(rc,Derta)); sum[o][1]=add(sum[lc][1],Get(rc,Derta+1)); } void build(int o,int l,int r){ L[o]=r-l+1; if(l==r){ sum[o][0]=sum[o][1]=a[l]; return;} int mid=l+r>>1,lc=o<<1,rc=(o<<1)|1; build(lc,l,mid); build(rc,mid+1,r); Merge(o,lc,rc,mid+1-l); } void update1(int o,int l,int r){ if(l==r){ sum[o][0]=sum[o][1]=w; return;} int mid=l+r>>1,lc=o<<1,rc=(o<<1)|1; pushdown(o,lc,rc); if(le<=mid) update1(lc,l,mid); else update1(rc,mid+1,r); Merge(o,lc,rc,mid+1-l); } void update2(int o,int l,int r){ if(l>=le&&r<=ri){ QADD(o,w); return;} int mid=l+r>>1,lc=o<<1,rc=(o<<1)|1; pushdown(o,lc,rc); if(le<=mid) update2(lc,l,mid); if(ri>mid) update2(rc,mid+1,r); Merge(o,lc,rc,mid+1-l); } void query(int o,int l,int r){ if(l>=le&&r<=ri){ ADD(A,Get(o,l-le)); return;} int mid=l+r>>1,lc=o<<1,rc=(o<<1)|1; pushdown(o,lc,rc); if(le<=mid) query(lc,l,mid); if(ri>mid) query(rc,mid+1,r); } inline void solve(){ while(m--){ scanf("%d",&O); if(O==1){ scanf("%d%d",&le,&w),update1(1,1,n);} else if(O==2){ scanf("%d%d",&le,&ri),A=0,query(1,1,n),printf("%d\n",A);} else{ scanf("%d%d%d",&le,&ri,&w),update2(1,1,n);} } } int main(){ init(); scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",a+i); build(1,1,n); solve(); return 0; }