傳送門
文章目錄
題意:
給你兩個長度為nnn的數組a,ba,ba,b,你需要完成如下四種操作:
思路:
思路還是比較簡單的,首先建一顆線段樹,線段樹中維護a,b,a2,b2,aba,b,a^2,b^2,aba,b,a2,b2,ab,讓后對于(2)(3)(2)(3)(2)(3)操作都可以給線段樹乘上一個矩陣來實現,對于(1)(1)(1)可以用線段樹區間加來實現,需要打lazylazylazy。
讓后這個題就做完了
實現起來還是比較麻煩的,需要明白矩陣乘的操作優先級是大于區間加標記的,所以在pushdownpushdownpushdown矩陣懶標記的時候需要將區間加的懶標記也更新一下。
更具體的:
下傳矩陣的懶標記:
這些都需要很細心的推公式,一開始錯了都能過樣例 。
LL a
,b
,c
,d
;a
=x
.maze
[0][0]; b
=x
.maze
[0][1];c
=x
.maze
[1][0]; d
=x
.maze
[1][1];LL ta
=tr
[u
].a
,tb
=tr
[u
].b
;tr
[u
].a
=(ta
*a
%mod
+tb
*c
%mod
)%mod
; tr
[u
].b
=(ta
*b
%mod
+tb
*d
%mod
)%mod
;ta
=tr
[u
].a2
,tb
=tr
[u
].b2
;tr
[u
].a2
=(a
*a
%mod
*ta
%mod
+c
*c
%mod
*tb
%mod
+2*a
*c
%mod
*tr
[u
].ab
%mod
)%mod
;tr
[u
].b2
=(b
*b
%mod
*ta
%mod
+d
*d
%mod
*tb
%mod
+2*b
*d
%mod
*tr
[u
].ab
%mod
)%mod
; tr
[u
].ab
=(a
*b
%mod
*ta
%mod
+(a
*d
%mod
+b
*c
%mod
)%mod
*tr
[u
].ab
%mod
+c
*d
%mod
*tb
%mod
)%mod
;ta
=tr
[u
].lazy1
,tb
=tr
[u
].lazy2
;tr
[u
].lazy1
=(a
*ta
%mod
+c
*tb
%mod
)%mod
;tr
[u
].lazy2
=(b
*ta
%mod
+d
*tb
%mod
)%mod
;tr
[u
].tag
=tr
[u
].tag
*x
;
對于下傳區間加的懶標記,這里只貼傳給aaa數組加的標記:
這里尤其需要注意一個細節,就是更新a2a^2a2的時候,需要更新為suma2+2x?suma+len?xsum_{a^2}+2x*sum_{a}+len*xsuma2?+2x?suma?+len?x,在xxx前面漏了個lenlenlen調了半年。。。
(tr
[u
].a2
+=(x
*x
%mod
*Len(u
)+2*tr
[u
].a
*x
%mod
)%mod
)%=mod
;(tr
[u
].a
+=Len(u
)*x
%mod
)%=mod
;(tr
[u
].ab
+=tr
[u
].b
*x
%mod
)%=mod
;(tr
[u
].lazy1
+=x
)%=mod
;
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<sstream>
#include<ctime>
#include<cstdlib>
#include<random>
#include<cassert>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define pb push_back
#define mk make_pair
#define Mid ((tr[u].l+tr[u].r)>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define db puts("---")
using namespace std
;
void rd_ac() { freopen("d://dp//date.in","r",stdin); freopen("d://dp//AC.txt","w",stdout); }
typedef long long LL
;
typedef unsigned long long ULL
;
typedef pair
<int,int> PII
;const int N
=300010,mod
=1000000007,INF
=0x3f3f3f3f;
const double eps
=1e-6;int n
;
struct Mat
{int n
,m
;LL maze
[2][2];Mat
() {}Mat
(int a
,int b
) {n
=a
; m
=b
;memset(maze
,0,sizeof(maze
));}void build_one() {memset(maze
,0,sizeof(maze
));for(int i
=0;i
<2;i
++)maze
[i
][i
]=1;} Mat
operator * (const Mat
&x
) const {Mat
now(2,2);memset(now
.maze
,0,sizeof(now
.maze
));for(int i
=0;i
<2;i
++) {for(int j
=0;j
<2;j
++) {for(int k
=0;k
<2;k
++) {(now
.maze
[i
][j
]+=(maze
[i
][k
]*x
.maze
[k
][j
])%mod
)%=mod
;}}}return now
;}
};
struct Node
{int l
,r
;LL a
,b
,ab
,lazy1
,lazy2
,a2
,b2
;Mat tag
;
}tr
[N
<<2];void pushup(int u
) {tr
[u
].a
=(tr
[L
].a
+tr
[R
].a
)%mod
;tr
[u
].b
=(tr
[L
].b
+tr
[R
].b
)%mod
;tr
[u
].ab
=(tr
[L
].ab
+tr
[R
].ab
)%mod
;tr
[u
].a2
=(tr
[L
].a2
+tr
[R
].a2
)%mod
;tr
[u
].b2
=(tr
[L
].b2
+tr
[R
].b2
)%mod
;
}void dateup1(int u
,Mat x
) {LL a
,b
,c
,d
;a
=x
.maze
[0][0]; b
=x
.maze
[0][1];c
=x
.maze
[1][0]; d
=x
.maze
[1][1];LL ta
=tr
[u
].a
,tb
=tr
[u
].b
;tr
[u
].a
=(ta
*a
%mod
+tb
*c
%mod
)%mod
; tr
[u
].b
=(ta
*b
%mod
+tb
*d
%mod
)%mod
;ta
=tr
[u
].a2
,tb
=tr
[u
].b2
;tr
[u
].a2
=(a
*a
%mod
*ta
%mod
+c
*c
%mod
*tb
%mod
+2*a
*c
%mod
*tr
[u
].ab
%mod
)%mod
;tr
[u
].b2
=(b
*b
%mod
*ta
%mod
+d
*d
%mod
*tb
%mod
+2*b
*d
%mod
*tr
[u
].ab
%mod
)%mod
; tr
[u
].ab
=(a
*b
%mod
*ta
%mod
+(a
*d
%mod
+b
*c
%mod
)%mod
*tr
[u
].ab
%mod
+c
*d
%mod
*tb
%mod
)%mod
;ta
=tr
[u
].lazy1
,tb
=tr
[u
].lazy2
;tr
[u
].lazy1
=(a
*ta
%mod
+c
*tb
%mod
)%mod
;tr
[u
].lazy2
=(b
*ta
%mod
+d
*tb
%mod
)%mod
;tr
[u
].tag
=tr
[u
].tag
*x
;
}void dateup2(int u
,LL x
) {(tr
[u
].a2
+=(x
*x
%mod
*Len(u
)+2*tr
[u
].a
*x
%mod
)%mod
)%=mod
;(tr
[u
].a
+=Len(u
)*x
%mod
)%=mod
;(tr
[u
].ab
+=tr
[u
].b
*x
%mod
)%=mod
;(tr
[u
].lazy1
+=x
)%=mod
;
}void dateup3(int u
,LL x
) {(tr
[u
].b2
+=(x
*x
%mod
*Len(u
)+2*tr
[u
].b
*x
%mod
)%mod
)%=mod
;(tr
[u
].b
+=Len(u
)*x
%mod
)%=mod
;(tr
[u
].ab
+=tr
[u
].a
*x
%mod
)%=mod
;(tr
[u
].lazy2
+=x
)%=mod
;
}void pushdown(int u
) {dateup1(L
,tr
[u
].tag
); dateup1(R
,tr
[u
].tag
); tr
[u
].tag
.build_one();dateup2(L
,tr
[u
].lazy1
); dateup2(R
,tr
[u
].lazy1
); tr
[u
].lazy1
=0;dateup3(L
,tr
[u
].lazy2
); dateup3(R
,tr
[u
].lazy2
); tr
[u
].lazy2
=0;
}void build(int u
,int l
,int r
) {tr
[u
]={l
,r
,0,0,0,0,0,0,0,Mat(2,2)};tr
[u
].tag
.build_one();if(l
==r
) {LL a
,b
; scanf("%lld%lld",&a
,&b
); tr
[u
].a
=a
; tr
[u
].b
=b
;tr
[u
].ab
=a
*b
%mod
;tr
[u
].a2
=a
*a
%mod
;tr
[u
].b2
=b
*b
%mod
;return;}build(L
,l
,Mid
); build(R
,Mid
+1,r
);pushup(u
);
}void change1(int u
,int l
,int r
,int tag
,int x
) {if(tr
[u
].l
>=l
&&tr
[u
].r
<=r
) {if(tag
) {dateup3(u
,x
);} else {dateup2(u
,x
);}return;}pushdown(u
);if(l
<=Mid
) change1(L
,l
,r
,tag
,x
);if(r
>Mid
) change1(R
,l
,r
,tag
,x
);pushup(u
);
}void change2(int u
,int l
,int r
,Mat x
) {if(tr
[u
].l
>=l
&&tr
[u
].r
<=r
) {dateup1(u
,x
);return;}pushdown(u
);if(l
<=Mid
) change2(L
,l
,r
,x
);if(r
>Mid
) change2(R
,l
,r
,x
);pushup(u
);
}LL
query(int u
,int l
,int r
) {if(tr
[u
].l
>=l
&&tr
[u
].r
<=r
) return tr
[u
].ab
;pushdown(u
);LL ans
=0;if(l
<=Mid
) (ans
+=query(L
,l
,r
))%=mod
;if(r
>Mid
) (ans
+=query(R
,l
,r
))%=mod
;return ans
;
}int main()
{
scanf("%d",&n
);build(1,1,n
);int m
; scanf("%d",&m
);while(m
--) {int op
,l
,r
,x
,y
;scanf("%d%d%d",&op
,&l
,&r
);if(op
==1) {scanf("%d%d",&x
,&y
);change1(1,r
,x
,l
,y
);} else if(op
==2) {Mat
now(2,2);now
.maze
[0][0]=3; now
.maze
[0][1]=3;now
.maze
[1][0]=2; now
.maze
[1][1]=mod
-2;change2(1,l
,r
,now
);} else if(op
==3) {Mat
now(2,2);now
.maze
[0][0]=0; now
.maze
[0][1]=1;now
.maze
[1][0]=1; now
.maze
[1][1]=0;change2(1,l
,r
,now
);} else if(op
==4) {printf("%lld\n",query(1,l
,r
));}}return 0;
}
總結
以上是生活随笔為你收集整理的HDU - 6967 G I love data structure 线段树维护矩阵 + 细节的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。