Codeforces 718C 线段树+矩乘
题意:
维护一个序列,支持两种操作:
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 线段树+矩乘的更多相关文章
- Bash and a Tough Math Puzzle CodeForces 914D 线段树+gcd数论
Bash and a Tough Math Puzzle CodeForces 914D 线段树+gcd数论 题意 给你一段数,然后小明去猜某一区间内的gcd,这里不一定是准确值,如果在这个区间内改变 ...
- 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 ...
- BZOJ 4085 丧心病狂的毒瘤题目 线段树+矩乘
思路: 一眼矩阵快速幂 再用线段树维护一下矩阵就完了... 我hhhhh 哎我还是too young,too simple 入了这个大坑 线段树维护9个值 以上 如果A+1 转移矩阵是这个样 ...
- Codeforces 938G 线段树分治 线性基 可撤销并查集
Codeforces 938G Shortest Path Queries 一张连通图,三种操作 1.给x和y之间加上边权为d的边,保证不会产生重边 2.删除x和y之间的边,保证此边之前存在 3.询问 ...
- codeforces 1136E 线段树
codeforces 1136E: 题意:给你一个长度为n的序列a和长度为n-1的序列k,序列a在任何时候都满足如下性质,a[i+1]>=ai+ki,如果更新后a[i+1]<ai+ki了, ...
- Z - New Year Tree CodeForces - 620E 线段树 区间种类 bitset
Z - New Year Tree CodeForces - 620E 这个题目还没有写,先想想思路,我觉得这个题目应该可以用bitset, 首先这个肯定是用dfs序把这个树转化成线段树,也就是二叉树 ...
- D - The Bakery CodeForces - 834D 线段树优化dp···
D - The Bakery CodeForces - 834D 这个题目好难啊,我理解了好久,都没有怎么理解好, 这种线段树优化dp,感觉还是很难的. 直接说思路吧,说不清楚就看代码吧. 这个题目转 ...
- B - Legacy CodeForces - 787D 线段树优化建图+dij最短路 基本套路
B - Legacy CodeForces - 787D 这个题目开始看过去还是很简单的,就是一个最短路,但是这个最短路的建图没有那么简单,因为直接的普通建图边太多了,肯定会超时的,所以要用线段树来优 ...
- CodeForces 343D 线段树维护dfs序
给定一棵树,初始时树为空 操作1,往某个结点注水,那么该结点的子树都注满了水 操作2,将某个结点的水放空,那么该结点的父亲的水也就放空了 操作3,询问某个点是否有水 我们将树进行dfs, 生成in[u ...
随机推荐
- day21 02 包的进阶
day21 02 包的进阶 1._init_.py文件的操作---导入包 根据day21 01 包的初识,建立的glance包,直接import glance后通过“包点包..点方法”是不能执行所要的 ...
- LINUX-字符设置和文件格式转换
dos2unix filedos.txt fileunix.txt 将一个文本文件的格式从MSDOS转换成UNIX unix2dos fileunix.txt filedos.txt 将一个文本文件的 ...
- OS X中crt中文乱码
SecureCRT中显示乱码的话,可以去设置为UTF-8编码: Session Options->Terminal->Appearance->Character Encoding,设 ...
- radial profiles of mean streamwise velocity at X/D=3
matlab code: load aver_ux_array.dat; load z_array.dat; r=z_array(:,); r=r.' r_j=0.00125; r_nor=r/d; ...
- 洛谷 4251 [SCOI2015]小凸玩矩阵
[题解] 二分答案+二分图匹配. 先二分最小值Min,然后扫一遍这个矩阵,把满足a[i][j]<=Min的i,j连边,之后跑二分图匹配,如果最大匹配数大于等于n-k+1,当前的Min即是合法的. ...
- BZOJ 1012 洛谷1198 最大数 maxnumber
用线段数维护即可 #include<cstdio> #include<algorithm> #define ls (cur<<1) #define rs (cur& ...
- 恶补数论(二) Baby-Step-Giant-Step 大步小步求离散模对数
知识概述 好吧,我承认这是我初三寒假就听过的知识,然而我现在早就高一了(又是寒假,只不过我已经在省选了...) 额,这是求离散模对数的一种算法 也就是求满足方程a^x≡b(mod p)的最小的x(其中 ...
- java nio--采用Selector实现Socket通信
server: /** * 选择器服务端 * Created by ascend on 2017/6/9 9:30. */ public class SelectorServer { // publi ...
- 根据判断数组不为空然后取他的值----数组不会为空---只能判断其size是否大于0
private List<Integer> classId=new ArrayList<Integer>(); business.getClassId()!=null 以上为错 ...
- 理解 LARGE_INTEGER的定义
http://bbs.csdn.net/topics/310239341 #if defined(MIDL_PASS) typedef struct _LARGE_INTEGER { #else // ...