题意:

维护一个序列,支持两种操作:
1.区间[l,r]的权值+x
2.询问区间[l,r]的函数和,即∑fib(x)这里的函数即斐波那契函数
数据范围:1≤n,q≤105

思路:
一般求斐波那契函数的方法可以考虑矩阵乘法,这里也是这样的。
我们不用线段树维护权值,我们用线段树维护线段树维护区间矩阵和。
有一个矩阵乘法的性质:A*B+A*C=A*(B+C)
在求斐波那契数列中,是A*F,A是变换矩阵,F是列矩阵
那么我们用线段树的lazy标记维护A矩阵,然后用sum维护F矩阵
之后在线段树上,就变成了区间更新乘以x。

//By SiriusRen
#include <bits/stdc++.h>
using namespace std;
const int mod=,N=;
int n,m,op,xx,yy,zz;
struct Matrix{
int a[][];
void init(){memset(a,,sizeof(a));}
void dia(){a[][]=a[][]=,a[][]=a[][]=;}
}sum[N<<],lazy[N<<],base;
Matrix operator*(Matrix a,Matrix b){
Matrix c;c.init();
for(int i=;i<;i++)
for(int j=;j<;j++)
for(int k=;k<;k++)
c.a[i][j]=(1ll*a.a[i][k]*b.a[k][j]+c.a[i][j])%mod;
return c;
}
Matrix operator+(Matrix a,Matrix b){
Matrix c;c.init();
for(int i=;i<;i++)
for(int j=;j<;j++)
c.a[i][j]=(a.a[i][j]+b.a[i][j])%mod;
return c;
}
Matrix operator^(Matrix a,int b){
Matrix c;c.dia();
while(b){
if(b&)c=c*a;
a=a*a,b>>=;
}return c;
}
void push_up(int pos){sum[pos]=sum[pos<<]+sum[pos<<|];}
void build(int l,int r,int pos){
if(l==r){scanf("%d",&xx);sum[pos]=base^(xx-);return;}
int mid=(l+r)>>,lson=pos<<,rson=pos<<|;
build(l,mid,lson),build(mid+,r,rson);
lazy[pos].dia(),push_up(pos);
}
void push_down(int pos,int lson,int rson){
lazy[lson]=lazy[lson]*lazy[pos],sum[lson]=sum[lson]*lazy[pos];
lazy[rson]=lazy[rson]*lazy[pos],sum[rson]=sum[rson]*lazy[pos];
lazy[pos].dia();
}
Matrix query(int l,int r,int pos,int L,int R){
if(l>=L&&r<=R)return sum[pos];
int mid=(l+r)>>,lson=pos<<,rson=pos<<|;
push_down(pos,lson,rson);
if(mid<L)return query(mid+,r,rson,L,R);
else if(mid>=R)return query(l,mid,lson,L,R);
else return query(l,mid,lson,L,R)+query(mid+,r,rson,L,R);
}
void insert(int l,int r,int pos,int L,int R,Matrix wei){
if(l>=L&&r<=R){sum[pos]=sum[pos]*wei;lazy[pos]=lazy[pos]*wei;return;}
int mid=(l+r)>>,lson=pos<<,rson=pos<<|;
push_down(pos,lson,rson);
if(mid<L)insert(mid+,r,rson,L,R,wei);
else if(mid>=R)insert(l,mid,lson,L,R,wei);
else insert(l,mid,lson,L,R,wei),insert(mid+,r,rson,L,R,wei);
push_up(pos);
}
int main(){
base.a[][]=base.a[][]=base.a[][]=;
scanf("%d%d",&n,&m),build(,n,);
while(m--){
scanf("%d%d%d",&op,&xx,&yy);
if(op==)scanf("%d",&zz),insert(,n,,xx,yy,base^zz);
else printf("%d\n",query(,n,,xx,yy).a[][]);
}
}

Codeforces 718C 线段树+矩乘的更多相关文章

  1. Bash and a Tough Math Puzzle CodeForces 914D 线段树+gcd数论

    Bash and a Tough Math Puzzle CodeForces 914D 线段树+gcd数论 题意 给你一段数,然后小明去猜某一区间内的gcd,这里不一定是准确值,如果在这个区间内改变 ...

  2. Codeforces Round #424 (Div. 2, rated, based on VK Cup Finals) Problem E (Codeforces 831E) - 线段树 - 树状数组

    Vasily has a deck of cards consisting of n cards. There is an integer on each of the cards, this int ...

  3. BZOJ 4085 丧心病狂的毒瘤题目 线段树+矩乘

    思路: 一眼矩阵快速幂 再用线段树维护一下矩阵就完了... 我hhhhh    哎我还是too young,too simple 入了这个大坑 线段树维护9个值 以上 如果A+1   转移矩阵是这个样 ...

  4. Codeforces 938G 线段树分治 线性基 可撤销并查集

    Codeforces 938G Shortest Path Queries 一张连通图,三种操作 1.给x和y之间加上边权为d的边,保证不会产生重边 2.删除x和y之间的边,保证此边之前存在 3.询问 ...

  5. codeforces 1136E 线段树

    codeforces 1136E: 题意:给你一个长度为n的序列a和长度为n-1的序列k,序列a在任何时候都满足如下性质,a[i+1]>=ai+ki,如果更新后a[i+1]<ai+ki了, ...

  6. Z - New Year Tree CodeForces - 620E 线段树 区间种类 bitset

    Z - New Year Tree CodeForces - 620E 这个题目还没有写,先想想思路,我觉得这个题目应该可以用bitset, 首先这个肯定是用dfs序把这个树转化成线段树,也就是二叉树 ...

  7. D - The Bakery CodeForces - 834D 线段树优化dp···

    D - The Bakery CodeForces - 834D 这个题目好难啊,我理解了好久,都没有怎么理解好, 这种线段树优化dp,感觉还是很难的. 直接说思路吧,说不清楚就看代码吧. 这个题目转 ...

  8. B - Legacy CodeForces - 787D 线段树优化建图+dij最短路 基本套路

    B - Legacy CodeForces - 787D 这个题目开始看过去还是很简单的,就是一个最短路,但是这个最短路的建图没有那么简单,因为直接的普通建图边太多了,肯定会超时的,所以要用线段树来优 ...

  9. CodeForces 343D 线段树维护dfs序

    给定一棵树,初始时树为空 操作1,往某个结点注水,那么该结点的子树都注满了水 操作2,将某个结点的水放空,那么该结点的父亲的水也就放空了 操作3,询问某个点是否有水 我们将树进行dfs, 生成in[u ...

随机推荐

  1. SQL学习笔记:基础SQL语句

    目录 语句特点 进入数据库 基本查询语句 SELECT DISTINCT WHERE AND/OR/NOT :逻辑运算符 ORDER BY :排序 基本修改语句 INSERT:添加语句 UPDATE: ...

  2. react入门----基础语法

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. [已解决]运行gunicorn失败:[ERROR] Connection in use 127.0.0.1 8080

    最近重新部署了一下应用程序,之后重新运行gunicorn,使用如下命令: gunicorn -b 0.0.0.0:8000 manage:app --reload 之后出现了一堆错误,具体错误内容如下 ...

  4. java,有用的代码片段

    在我们写程序的过程中,往往会经常遇到一些常见的功能.而这些功能或效果往往也是相似的,解决方案也相似.下面是我在写代码的过程中总结的一些有用的代码片段. 1.在多线程环境中操作同一个Collection ...

  5. nyoj 4 ASCII码排序(set,multiset)

    ASCII码排序 时间限制:3000 ms  |  内存限制:65535 KB 难度:2   描述 输入三个字符(可以重复)后,按各字符的ASCII码从小到大的顺序输出这三个字符.   输入 第一行输 ...

  6. Oracle操作管理之用户和角色

    1.用户管理 (1)建立用户(数据库验证) CREATE USER smith IDENTIFIED BY smith_pwd DEFAULTTABLESPACE users TEMPORARY TA ...

  7. 欧拉回路输出(DFS,不用回溯!)Watchcow POJ 2230

    Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 8109   Accepted: 3551   Special Judge D ...

  8. O - Treats for the Cows 区间DP

    FJ has purchased N (1 <= N <= 2000) yummy treats for the cows who get money for giving vast am ...

  9. 武大OJ 612. Catch the sheep

    Description Old Sama is a great and powerful magician in the word. One day, a little girl, Anny, tou ...

  10. 20、Java并发性和多线程-Slipped Conditions

    以下内容转自http://ifeve.com/slipped-conditions/: 所谓Slipped conditions,就是说, 从一个线程检查某一特定条件到该线程操作此条件期间,这个条件已 ...