ZOJ 3772 Calculate the Function(線段樹+矩陣)
題目連結:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5235
題意:
題意很好懂 就是
給定一個數列 a1,a2,...,an
對於一個遞推式 F[L]=a[L],F[L+1]=a[L+1],F[X] = F[X-1]+F[X-2]*aX,
然後給定m個詢問,每次給定L,R, 求F(R);
對於這個遞推式 每一項我們可以得到一個狀態轉移矩陣
| F[x] | | 1 , a[x] |
| |= | |
| F[x-1] | | 1 , 0 |
所以我們可以用線段樹維護這個矩陣,值得因為矩陣的乘法滿足結合律不滿足交換律
因此我們在維護的時候需要注意一下 F[R] = (Mr*Mr-1*.....*Ml+2)*A;要注意維護的時候
要保證好這個順序。
程式碼如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define PB push_back
#define MP make_pair
#define REP(i,n) for(int i=0;i<(n);++i)
#define FOR(i,l,h) for(int i=(l);i<=(h);++i)
#define DWN(i,h,l) for(int i=(h);i>=(l);--i)
#define IFOR(i,h,l,v) for(int i=(h);i<=(l);i+=(v))
#define CLR(vis) memset(vis,0,sizeof(vis))
#define MST(vis,pos) memset(vis,pos,sizeof(vis))
#define MAX3(a,b,c) max(a,max(b,c))
#define MAX4(a,b,c,d) max(max(a,b),max(c,d))
#define MIN3(a,b,c) min(a,min(b,c))
#define MIN4(a,b,c,d) min(min(a,b),min(c,d))
#define PI acos(-1.0)
#define INF 1000000000
#define LINF 1000000000000000000LL
#define eps 1e-8
#define LL long long
#define lson(id) id<<1
#define rson(id) id<<1|1
using namespace std;
const LL mod = 1e9+7;
const int maxn = 1e5+10;
int a[maxn];
struct matrix{
LL m[2][2];
matrix(){CLR(m);}
matrix operator *(const struct matrix &tmp){
matrix ans;
REP(i,2){
REP(j,2){
ans.m[i][j]=0;
REP(k,2)
ans.m[i][j]=(ans.m[i][j]+m[i][k]*tmp.m[k][j])%mod;
}
}
return ans;
}
};
struct seg_tree{
int l,r;
matrix ans;
}t[maxn<<2];
void build(int id,int l,int r){
t[id].l=l,t[id].r=r;
if(l==r){
t[id].ans.m[0][0]=1;
t[id].ans.m[0][1]=a[l];
t[id].ans.m[1][0]=1;
t[id].ans.m[1][1]=0;
//cout<<"*** "<<t[id].ans.m[0][1]<<endl;
return;
}
int mid=(l+r)>>1;
build(lson(id),l,mid);
build(rson(id),mid+1,r);
t[id].ans=t[rson(id)].ans*t[lson(id)].ans;
}
matrix query(int id,int l,int r){
if(l==t[id].l&&r==t[id].r) return t[id].ans;
int mid = (t[id].l+t[id].r)>>1;
if(mid>=r) return query(lson(id),l,r);
else if(mid<l) return query(rson(id),l,r);
else return query(rson(id),mid+1,r)*query(lson(id),l,mid);
}
int main()
{
int t,n,m,l,r;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
FOR(i,1,n) scanf("%d",&a[i]);
build(1,1,n);
REP(i,m){
scanf("%d%d",&l,&r);
if(r-l>=2){
matrix tmp;
tmp.m[0][0]=a[l+1];
tmp.m[1][0]=a[l];
matrix ans =query(1,l+2,r)*tmp;
printf("%lld\n",ans.m[0][0]);
}
else
printf("%d\n",a[r]);
}
}
return 0;
}
相關文章
- 線段樹+差分——【模板】樹狀陣列2陣列
- hdu 4836 The Query on the Tree(線段樹or樹狀陣列)陣列
- 矩陣樹定理矩陣
- HDU 1556 Color the ball(線段樹|樹狀陣列)陣列
- 線~段~樹
- 線段樹
- 矩陣樹定理 BEST 定理矩陣
- light oj 1080 線段樹和樹狀陣列陣列
- 線段樹 hate it
- 【模版】線段樹
- 01 線段樹
- 線段樹--RMQMQ
- 李超線段樹
- 線段樹模板
- 動態規劃-最大子矩陣和(ZOJ 1074 TO THE MAX )動態規劃矩陣
- 矩陣樹定理與BEST定理矩陣
- ut.cpp 最大線段並減線段交 [線段樹]
- 線段樹筆記筆記
- 線段樹入門
- 權值線段樹
- 線段樹進階
- 線性代數--矩陣矩陣
- 最大子段和 | 最大子矩陣 | 最大M子段和矩陣
- POJ 3468 【區間修改+區間查詢 樹狀陣列 | 線段樹 | 分塊】陣列
- 線段樹(毒瘤)總結
- 線段樹模板總結
- 深入理解線段樹
- 線段樹入門理解
- 線段樹(超詳解)
- 第二課——線段樹
- 線段樹簡單思路
- 線段樹擴充套件套件
- 線段樹 transformation——hdu 4578ORM
- 可持久化線段樹持久化
- 【.NET 與樹莓派】矩陣按鍵樹莓派矩陣
- 線段樹 - 多組圖帶你從頭到尾徹底理解線段樹
- 矩陣加速線性遞推矩陣
- 資料結構之樹( 線段樹,字典樹)資料結構