日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

CodeForces - 1252K Addition Robot(线段树维护矩阵)

發(fā)布時間:2024/4/11 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 CodeForces - 1252K Addition Robot(线段树维护矩阵) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

題目鏈接:點擊查看

題目大意:給出一個只由 A 和 B 組成的字符串 s ,需要完成 m 次操作,每次操作分為兩種類型:

  • 1 l r :將 [ l , r ] 內(nèi)的字符串 A 變成 B,B 變成 A
  • 2 l r a b:從左到右掃一遍字符串 s 的 [ l , r ] ,并求出最后的 a 和 b
  • 如果 s[ i ] == ' B ' : b = a + b
  • 如果 s[ i ] == ' A ' : a = a + b
  • 題目分析:維護一段連續(xù)的 a 和 b 的變化,通過觀察后不難發(fā)現(xiàn)其實可以用矩陣去維護:

    這樣操作二就得以維護了,但操作一該如何維護呢,如果只是觀察單純的一個 A 和 B 的轉移矩陣,可以發(fā)現(xiàn)是經(jīng)過上下翻轉然后再經(jīng)過左右翻轉得到的,利用矩陣乘法多觀察一下,當 n 大于一時,執(zhí)行操作一后,同樣也是需要將矩陣進行上下翻轉然后左右翻轉再得到的,證明的話我也不會,畢竟比賽的時候也不會考察證明嘛

    所以對于操作一,寫一個 reverse 函數(shù)執(zhí)行上述操作即可

    區(qū)間查詢的話,可以用線段樹維護矩陣,這樣可以實現(xiàn)區(qū)間更新以及區(qū)間查詢

    代碼:
    ?

    #include<iostream> #include<cstdio> #include<string> #include<ctime> #include<cmath> #include<cstring> #include<algorithm> #include<stack> #include<climits> #include<queue> #include<map> #include<set> #include<sstream> #include<cassert> #include<bitset> #include<unordered_map> using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=1e5+100;const int mod=1e9+7;char s[N];struct Ma {LL a[2][2];Ma operator*(const Ma& t){Ma ans;for(int i=0;i<2;i++)for(int j=0;j<2;j++){ans.a[i][j]=0;for(int k=0;k<2;k++)ans.a[i][j]=(ans.a[i][j]+a[i][k]*t.a[k][j])%mod;}return ans;} }one;struct Node {int l,r;int rev;Ma maze; }tree[N<<2];void pushup(int k) {tree[k].maze=tree[k<<1].maze*tree[k<<1|1].maze; }void reverse(int k) {swap(tree[k].maze.a[0][0],tree[k].maze.a[0][1]);swap(tree[k].maze.a[1][0],tree[k].maze.a[1][1]);swap(tree[k].maze.a[0][0],tree[k].maze.a[1][0]);swap(tree[k].maze.a[0][1],tree[k].maze.a[1][1]); }void pushdown(int k) {if(tree[k].rev){tree[k].rev=0;tree[k<<1].rev^=1;tree[k<<1|1].rev^=1;reverse(k<<1);reverse(k<<1|1);} }void build(int k,int l,int r) {tree[k].l=l;tree[k].r=r;tree[k].rev=0;if(l==r){if(s[l]=='A'){tree[k].maze.a[0][0]=1;tree[k].maze.a[0][1]=0;tree[k].maze.a[1][0]=1;tree[k].maze.a[1][1]=1;}else{tree[k].maze.a[0][0]=1;tree[k].maze.a[0][1]=1;tree[k].maze.a[1][0]=0;tree[k].maze.a[1][1]=1;}return;}int mid=l+r>>1;build(k<<1,l,mid);build(k<<1|1,mid+1,r);pushup(k); }void update(int k,int l,int r) {if(tree[k].r<l||tree[k].l>r)return;if(tree[k].l>=l&&tree[k].r<=r){reverse(k);tree[k].rev^=1;return;}pushdown(k);update(k<<1,l,r);update(k<<1|1,l,r);pushup(k); }Ma query(int k,int l,int r) {if(tree[k].r<l||tree[k].l>r)return one;if(tree[k].l>=l&&tree[k].r<=r)return tree[k].maze;pushdown(k);return query(k<<1,l,r)*query(k<<1|1,l,r); }void init() {one.a[0][0]=1;one.a[0][1]=0;one.a[1][0]=0;one.a[1][1]=1; }int main() { #ifndef ONLINE_JUDGE // freopen("data.in.txt","r",stdin); // freopen("data.out.txt","w",stdout); #endif // ios::sync_with_stdio(false);init();int n,m;scanf("%d%d",&n,&m);scanf("%s",s+1);build(1,1,n);while(m--){int op;scanf("%d",&op);if(op==1){int l,r;scanf("%d%d",&l,&r);update(1,l,r);}else{int l,r,a,b;scanf("%d%d%d%d",&l,&r,&a,&b);Ma ans2=query(1,l,r);Ma ans1;ans1.a[0][0]=a;ans1.a[0][1]=b;ans1.a[1][0]=0;ans1.a[1][1]=0;Ma ans=ans1*ans2;printf("%lld %lld\n",ans.a[0][0],ans.a[0][1]);}}return 0; }

    ?

    超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生

    總結

    以上是生活随笔為你收集整理的CodeForces - 1252K Addition Robot(线段树维护矩阵)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。