zoukankan      html  css  js  c++  java
  • Codeforces Round #373 (Div. 2)

    A,B,C傻逼题,就不说了。

    E题:

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <cmath>
      5 #include <algorithm>
      6 using namespace std;
      7 const int maxn=100005,mod=1000000007;
      8 typedef long long int64;
      9 int n,m,fuck[maxn<<2];
     10 int64 a[maxn],s1[maxn<<2],s2[maxn<<2];
     11 struct Matrix{
     12     int n,m;
     13     int64 a[2][2];
     14     void clear(){for (int i=0;i<2;i++)for (int j=0;j<2;j++)a[i][j]=0;}
     15 }wn,lazy[maxn<<2],a0,t1,t2,b;
     16 Matrix operator *(Matrix x,Matrix y){
     17     Matrix ans; ans.n=x.n,ans.m=y.m;
     18     ans.clear(); int N=ans.n,M=ans.m;
     19     for (int i=0;i<N;i++){
     20         for (int j=0;j<M;j++){
     21             for (int k=0;k<x.m;k++){
     22                 ans.a[i][j]=(ans.a[i][j]+x.a[i][k]*y.a[k][j]%mod)%mod;
     23             }
     24         }
     25     }
     26     return ans;
     27 }
     28 Matrix qpow(Matrix x,int64 y){
     29     if (y==0) return wn;
     30     if (y==1) return x;
     31     Matrix d=qpow(x,y/2); d=d*d;
     32     if (y&1) return d*x;
     33     else return d;
     34 }
     35 void build(int k,int l,int r){
     36     lazy[k]=wn; fuck[k]=-1;
     37     if (l==r) return;
     38     int mid=(l+r)>>1;
     39     build(k*2,l,mid),build(k*2+1,mid+1,r);
     40 }
     41 void pushdown(int k,Matrix x){
     42     Matrix y=x;
     43     int64 oy=s1[k],zx=s2[k],A,B,C;
     44     t1=a0*x; A=t1.a[0][0]; x=x*b;
     45     t1=a0*x; B=t1.a[0][0]; x=x*b;
     46     t1=a0*x; C=t1.a[0][0];
     47     s1[k]=(oy*A%mod+zx*B%mod)%mod;
     48     s2[k]=(oy*B%mod+zx*C%mod)%mod;
     49     if (fuck[k]!=-1){lazy[k]=lazy[k]*y,lazy[k]=lazy[k]*b;}
     50     else lazy[k]=y;
     51     fuck[k]=1;
     52 }
     53 void insert(int k,int l,int r,int x,int64 y1,int64 y2){
     54     if (l==r&&r==x){s1[k]=y1%mod,s2[k]=y2%mod;return;}
     55     int mid=(l+r)>>1;
     56     if (x<=mid) insert(k*2,l,mid,x,y1,y2);
     57     else insert(k*2+1,mid+1,r,x,y1,y2);
     58     s1[k]=(s1[k*2]+s1[k*2+1])%mod,s2[k]=(s2[k*2]+s2[k*2+1])%mod;
     59 }
     60 void change(int k,int l,int r,int x,int y,Matrix t){
     61     if (fuck[k]!=-1){
     62         if (l!=r){pushdown(k*2,lazy[k]),pushdown(k*2+1,lazy[k]);}
     63         lazy[k]=wn; fuck[k]=-1;
     64     }
     65     if (l>=x&&r<=y){pushdown(k,t);return;}
     66     int mid=(l+r)>>1;
     67     if (x<=mid) change(k*2,l,mid,x,y,t);
     68     if (y>mid) change(k*2+1,mid+1,r,x,y,t);
     69     s1[k]=(s1[k*2]+s1[k*2+1])%mod,s2[k]=(s2[k*2]+s2[k*2+1])%mod;
     70 }
     71 int64 query(int k,int l,int r,int x,int y){
     72     if (fuck[k]!=-1){
     73         if (l!=r){pushdown(k*2,lazy[k]),pushdown(k*2+1,lazy[k]);}
     74         lazy[k]=wn; fuck[k]=-1;
     75     }
     76     if (l>=x&&r<=y) return s2[k]%mod;
     77     int mid=(l+r)>>1; int64 temp=0;
     78     if (x<=mid) temp=(temp+query(k*2,l,mid,x,y))%mod;
     79     if (y>mid) temp=(temp+query(k*2+1,mid+1,r,x,y))%mod;
     80     return temp;
     81 }
     82 int main(){
     83     scanf("%d%d",&n,&m); a0.clear(),t1.clear(),b.clear(),wn.clear();
     84     a0.n=1,a0.m=2; a0.a[0][0]=0,a0.a[0][1]=1;
     85     wn.n=2,wn.m=2;
     86     for (int i=0;i<2;i++)
     87         for (int j=0;j<2;j++){
     88             if (i==j) wn.a[i][j]=1;
     89             else wn.a[i][j]=0;
     90         }
     91     build(1,1,n);
     92     b.n=b.m=2;
     93     for (int i=0;i<2;i++){
     94         for (int j=0;j<2;j++){
     95             if (!i&&!j) b.a[i][j]=0;
     96             else b.a[i][j]=1;
     97         }
     98     }
     99     memset(s1,0,sizeof(s1));
    100     memset(s2,0,sizeof(s2));
    101     for (int i=1;i<=n;i++){
    102         scanf("%I64d",&a[i]);
    103         t1=a0*qpow(b,a[i]);
    104         t2=a0*qpow(b,a[i]-1);
    105         insert(1,1,n,i,t2.a[0][0],t1.a[0][0]);
    106     }
    107     for (int type,l,r,x;m;m--){
    108         scanf("%d%d%d",&type,&l,&r);
    109         if (type==1){
    110             scanf("%d",&x);
    111             t1=qpow(b,x-1);
    112             change(1,1,n,l,r,t1);
    113         }else{printf("%I64d
    ",query(1,1,n,l,r)%mod);}
    114     }
    115     return 0;
    116 }
    View Code

    链接:http://codeforces.com/contest/719/problem/E

    题目大意:给定一个长度为n的序列ai,m个操作,有以下两种操作,1种是把l~r这一段数加上一个数x,另1种是询问l~r的f[ai]之和,f[i]为斐波那契数列的第i项,令f[1]=f[2]=1,f[i]=f[i-2]+f[i-1](i>2). n,m<=10^5  ,  1<=ai,x<=10^9;

    做法:这题显然是要用线段树和矩阵快速幂,但是是区间修改不好维护,但是对于斐波那契数列有个结论就是f[n+m]=f[n-1]*f[m]+f[n]*f[m+1],有了这个就很好做了,如下:

    f(a+x) = f(x+1)f(a) + f(x)f(a-1)
    f(a-1+x) = f(x-1)f(a-1) + f(x)f(a)
    令s1(l,r)为区间内所有f(a[i])的和
    令s2(l,r)为区间内所有f(a[i]-1)的和
    然后线段树维护这两个就行了,每次计算某个f(x)的值就拿矩阵快速幂(8*logn)。

    这样的做法是nlogn^2的,加上线段树的常数是过不了的,我们得考虑矩阵乘法那一部分,我们真的需要在每次传标记的时候都用logn的时间来计算f(x)吗,显然是不需要的,我们只要把lazy标记设为一个矩阵即可,为b^x(令b为用矩阵乘法求斐波那契数列时候的矩阵),合并标记的时候就把这个矩阵乘一下即可,总时间复杂度降为了nlogn,能过。这题首先用结论把问题转化为了支持区间修改,再利用了每次计算的重复,巧妙地把lazy标记定为矩阵,进一步降低时间复杂度,一个好题。

  • 相关阅读:
    ps 玻璃效果
    svn 官方下载
    svn
    c# form 无标题
    app Inventor google 拖放手机代码块
    paas
    java 延迟
    c# 执行 cmd
    c # xml操作 (无法将类型为“System.Xml.XmlComment”的对象强制转换为类型“System.Xml.XmlElement”)
    eclipse 安装插件 link方式
  • 原文地址:https://www.cnblogs.com/OYzx/p/5903723.html
Copyright © 2011-2022 走看看