Codeforces Round #373 (Div. 1) C.Sasha and Array

    xiaoxiao2023-03-24  3

    题目大意:给你一个长度为n的数列an,有两种操作

    1、将L到R的ai加上X

    2、询问L到R之间,f(aL)+f(aL+1)+……+f(aR)的和

    考虑维护fib数列的转移

    区间加,就相当于区间乘上一个矩阵

    那么我们直接维护矩阵的合并和懒标记下推就可以了

    乘的矩阵要预处理一下不然会多一个log的复杂度

    #include<map> #include<cmath> #include<queue> #include<vector> #include<cstdio> #include<string> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int N=2; const long long MOD=1000000007; struct Matrix { long long grid[N][N]; int row,col; Matrix():row(N),col(N) { memset(grid, 0, sizeof grid); } Matrix(int row, int col):row(row),col(col) { memset(grid, 0, sizeof grid); } Matrix operator *(const Matrix &b) { Matrix res(row, b.col); for(int i = 0; i<res.row; i++) for(int j = 0; j<res.col; j++) for(int k = 0;k<col; k++) res[i][j] = (res[i][j] + grid[i][k] * b.grid[k][j]) % MOD; return res; } Matrix operator ^(long long exp) { Matrix res(row, col); for(int i = 0; i < row; i++) res[i][i] = 1; Matrix temp = *this; for(; exp > 0; exp >>= 1, temp = temp * temp) if(exp & 1) res = temp * res; return res; } long long* operator[](int index) { return grid[index]; } void print() { for(int i = 0; i <row; i++) { for(int j = 0; j < col-1; j++) printf("%d ",grid[i][j]); printf("%d\n",grid[i][col-1]); } } }; struct tree { int l,r; long long x[2]; long long s[3][3]; }tr[800001]; inline long long cale(int d) { Matrix c(2,2); if(d<=2&&d>0) return 1; if(d==0) return 0; c[0][0]=0; c[0][1]=1; c[1][0]=1; c[1][1]=1; if(d>2) c=c^(d-2); return (c[0][1]+c[1][1])%MOD; } int a[100001]; inline void up(int p) { tr[p].x[0]=(tr[p*2].x[0]+tr[p*2+1].x[0])%MOD; tr[p].x[1]=(tr[p*2].x[1]+tr[p*2+1].x[1])%MOD; } inline void push(int p) { long long x0=tr[p*2].x[0],x1=tr[p*2].x[1]; tr[p*2].x[0]=(x0*tr[p].s[1][1]+x1*tr[p].s[2][1])%MOD; tr[p*2].x[1]=(x0*tr[p].s[1][2]+x1*tr[p].s[2][2])%MOD; x0=tr[p*2+1].x[0],x1=tr[p*2+1].x[1]; tr[p*2+1].x[0]=(x0*tr[p].s[1][1]+x1*tr[p].s[2][1])%MOD; tr[p*2+1].x[1]=(x0*tr[p].s[1][2]+x1*tr[p].s[2][2])%MOD; long long s11=tr[p*2].s[1][1],s12=tr[p*2].s[1][2],s21=tr[p*2].s[2][1],s22=tr[p*2].s[2][2]; tr[p*2].s[1][1]=(s11*tr[p].s[1][1]+s12*tr[p].s[2][1])%MOD; tr[p*2].s[1][2]=(s11*tr[p].s[1][2]+s12*tr[p].s[2][2])%MOD; tr[p*2].s[2][1]=(s21*tr[p].s[1][1]+s22*tr[p].s[2][1])%MOD; tr[p*2].s[2][2]=(s21*tr[p].s[1][2]+s22*tr[p].s[2][2])%MOD; s11=tr[p*2+1].s[1][1],s12=tr[p*2+1].s[1][2],s21=tr[p*2+1].s[2][1],s22=tr[p*2+1].s[2][2]; tr[p*2+1].s[1][1]=(s11*tr[p].s[1][1]+s12*tr[p].s[2][1])%MOD; tr[p*2+1].s[1][2]=(s11*tr[p].s[1][2]+s12*tr[p].s[2][2])%MOD; tr[p*2+1].s[2][1]=(s21*tr[p].s[1][1]+s22*tr[p].s[2][1])%MOD; tr[p*2+1].s[2][2]=(s21*tr[p].s[1][2]+s22*tr[p].s[2][2])%MOD; tr[p].s[1][1]=1; tr[p].s[1][2]=0; tr[p].s[2][1]=0; tr[p].s[2][2]=1; } inline void build(int p,int l,int r) { tr[p].l=l; tr[p].r=r; if(l!=r) { int mid=(l+r)/2; build(p*2,l,mid); build(p*2+1,mid+1,r); up(p); tr[p].s[1][1]=1; tr[p].s[1][2]=0; tr[p].s[2][1]=0; tr[p].s[2][2]=1; } else { tr[p].x[0]=cale(a[l]-1); tr[p].x[1]=cale(a[l]); tr[p].s[1][1]=1; tr[p].s[1][2]=0; tr[p].s[2][1]=0; tr[p].s[2][2]=1; } } inline long long query(int p,int l,int r) { if(l<=tr[p].l&&tr[p].r<=r) return tr[p].x[1]; else { push(p); int mid=(tr[p].l+tr[p].r)/2; long long ans=0; if(l<=mid) ans+=query(p*2,l,r); if(r>mid) ans+=query(p*2+1,l,r); ans=ans%MOD; return ans; } } Matrix c(2,2); long long xt[3][3]; inline void change(int p,int l,int r,int x) { if(l<=tr[p].l&&tr[p].r<=r) { // c.print(); long long x0=tr[p].x[0],x1=tr[p].x[1]; tr[p].x[0]=(x0*c[0][0]+x1*c[1][0])%MOD; tr[p].x[1]=(x0*c[0][1]+x1*c[1][1])%MOD; long long s11=tr[p].s[1][1],s12=tr[p].s[1][2],s21=tr[p].s[2][1],s22=tr[p].s[2][2]; tr[p].s[1][1]=(s11*c[0][0]+s12*c[1][0])%MOD; tr[p].s[1][2]=(s11*c[0][1]+s12*c[1][1])%MOD; tr[p].s[2][1]=(s21*c[0][0]+s22*c[1][0])%MOD; tr[p].s[2][2]=(s21*c[0][1]+s22*c[1][1])%MOD; } else { push(p); int mid=(tr[p].l+tr[p].r)/2; if(l<=mid) change(p*2,l,r,x); if(r>mid) change(p*2+1,l,r,x); up(p); } } int main() { int n,m; scanf("%d%d",&n,&m); int i; for(i=1;i<=n;i++) scanf("%d",&a[i]); build(1,1,n); int x,s,t; for(i=1;i<=m;i++) { scanf("%d",&x); if(x==2) { scanf("%d%d",&s,&t); printf("%I64d\n",query(1,s,t)); } else { scanf("%d%d%d",&s,&t,&x); c[0][0]=0; c[0][1]=1; c[1][0]=1; c[1][1]=1; c=c^x; change(1,s,t,x); } } return 0; }

    转载请注明原文地址: https://ju.6miu.com/read-1200247.html
    最新回复(0)