题目链接:点击查看

题目大意:给出一个只由 A 和 B 组成的字符串 s ,需要完成 m 次操作,每次操作分为两种类型:

  1. 1 l r :将 [ l , r ] 内的字符串 A 变成 B,B 变成 A
  2. 2 l r a b:从左到右扫一遍字符串 s 的 [ l , r ] ,并求出最后的 a 和 b
    1. 如果 s[ i ] == ' B ' : b = a + b
    2. 如果 s[ i ] == ' A ' : a = a + b

题目分析:维护一段连续的 a 和 b 的变化,通过观察后不难发现其实可以用矩阵去维护:

这样操作二就得以维护了,但操作一该如何维护呢,如果只是观察单纯的一个 A 和 B 的转移矩阵,可以发现是经过上下翻转然后再经过左右翻转得到的,利用矩阵乘法多观察一下,当 n 大于一时,执行操作一后,同样也是需要将矩阵进行上下翻转然后左右翻转再得到的,证明的话我也不会,毕竟比赛的时候也不会考察证明嘛

所以对于操作一,写一个 reverse 函数执行上述操作即可

区间查询的话,可以用线段树维护矩阵,这样可以实现区间更新以及区间查询

代码:

#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;
}

CodeForces - 1252K Addition Robot(线段树维护矩阵)相关推荐

  1. 【2019牛客暑期多校训练营(第二场)- E】MAZE(线段树优化dp,dp转矩阵乘法,线段树维护矩阵乘法)

    题干: 链接:https://ac.nowcoder.com/acm/contest/882/E?&headNav=acm 来源:牛客网 Given a maze with N rows an ...

  2. HDU - 6967 G I love data structure 线段树维护矩阵 + 细节

    传送门 文章目录 题意: 思路: 题意: 给你两个长度为nnn的数组a,ba,ba,b,你需要完成如下四种操作: 思路: 思路还是比较简单的,首先建一颗线段树,线段树中维护a,b,a2,b2,aba, ...

  3. 2019ICPC(南昌) - Hello 2019(动态规划+线段树维护矩阵)

    题目链接:点击查看 题目大意:给出一个长度为n的只由数字组成的字符串,再给出m个询问,每次询问给出闭区间[l,r],求区间内想要包含"9102",但不包含"8102&qu ...

  4. CF719E. Sasha and Array [线段树维护矩阵]

    CF719E. Sasha and Array 题意: 对长度为 n 的数列进行 m 次操作, 操作为: a[l..r] 每一项都加一个常数 C, 其中 0 ≤ C ≤ 10^9 求 F[a[l]]+ ...

  5. [动态dp]线段树维护转移矩阵

    背景:czy上课讲了新知识,从未见到过,总结一下. 所谓动态dp,是在动态规划的基础上,需要维护一些修改操作的算法. 这类题目分为如下三个步骤:(都是对于常系数齐次递推问题) 1先不考虑修改,不考虑区 ...

  6. Codeforces Round #343 (Div. 2) D. Babaei and Birthday Cake 线段树维护dp

    D. Babaei and Birthday Cake 题目连接: http://www.codeforces.com/contest/629/problem/D Description As you ...

  7. Codeforces Round #742 (Div. 2) E. Non-Decreasing Dilemma (线段树维护区间连续问题)

    题意: 操作1:把x位置的数字修改成y. 操作2:查询[l,r]之间不下降序列的个数. 题解: 线段树维护区间和问题 (这是套路,想不到只能说做题少别打我) . 用五个变量进行维护. sum区间总个数 ...

  8. Codeforces Round #603 (Div. 2) E. Editor 线段树维护括号序列

    传送门 文章目录 题意: 思路: 题意: 思路: 首先一个括号序列合法的条件可以转化成两个(左括号代价为111,右括号代价为−1-1−1): (1) 左括号个数等于右括号个数. (2) 括号的前缀和非 ...

  9. Codeforces 833B 题解(DP+线段树)

    题面 传送门:http://codeforces.com/problemset/problem/833/B B. The Bakery time limit per test2.5 seconds m ...

最新文章

  1. C++ Primer英文版(第5版)
  2. libevent 实现的socket 通信 server以及解决找不到动态库的方法
  3. [转]Linux 进程间通信:共享内存
  4. apache shiro jar包_只需要6个步骤,springboot集成shiro,并完成登录
  5. spring mvc使用html页面,使用Spring MVC的纯HTML页面应用程序
  6. 微分方程的数值解法与程序实现 pdf_初中数学知识点|一元一次方程的概念及讲解(二)建议收藏!内含pdf版...
  7. 比特币 源代码_GitHub遭黑客攻击:窃取数百源码并勒索比特币,数量惊人!
  8. PHP冒泡排序(Bubble Sort)算法详解
  9. tkinter要安装吗 苹果_建造存10万斤的苹果保鲜冷库安装工程要考虑哪些因素?...
  10. kettle spoon判断增量更新_【论文推荐】张斌等:基于改进 SOINN 算法的恶意软件增量检测方法...
  11. PHP语言编程实现采集远程图片资源
  12. 需求不容易确定的项目不要接
  13. Zookeeper,Hbase 伪分布,集群搭建
  14. 带你啃透深度学习必学“圣经”花书!(附带论文代码精读讲解)
  15. 带头节点 (非头指针) 双向链表 (doubly linked list)
  16. 泛函分析笔记0:绪论
  17. 在企业工作一年多的几点感悟
  18. 统信UOS应用商店十月活动
  19. 绝地大逃杀官方指定迅游加速
  20. Axure元件之文本框的案例

热门文章

  1. 深度linux卡顿,Deepin很卡怎么办?Deepin卡顿解决方法盘点
  2. CORS 跨域-哪些操作不受同源限制
  3. MySQL高级 - 日志 - 二进制日志(statement)
  4. MySQL高级 - 常用工具 - mysqlimport与source
  5. synchronized锁的升级
  6. 自定义线程池-线程类和任务类代码实现
  7. 自定义线程池-参数设计分析
  8. 数据库-聚合函数-max函数
  9. Linux环境下安装Redis
  10. Spring Session官方介绍及spring框架学习方法