题目描述

你有一个长度为 \(n\) 的数列 \(\{a_n\}\) ,这个数列由 \(0,1\) 组成,进行 \(m\) 个的操作:

\(1\ l\ r\) :把数列区间$ [l,r]$ 内的所有数取反。即 \(0\) 变成 \(1\) ,\(1\) 变成 \(0\) 。

\(2\ l\ r\) :询问数列在区间 \([l, r]\) 内共有多少个本质不同的子序列。

输入输出格式

输入格式:

第一行包含两个整数 \(n,m\),意义如上所述。

接下来一行包含 \(n\) 个数,表示数列 \(\{a_n\}\) 。

接下来 \(m\) 行,每行包含三个数,表示一个操作,操作格式如上所述。

输出格式:

对于每个询问,输出答案模 \(10^{9}+7\) 的结果。

思路

前置技能:

维护一个长度为 \(n\) 的 \(3*3\) 的 \(0/1\) 矩阵序列

  1. 交换区间 \([l,r]\) 中所有矩阵的第一行和第二行

  2. 查询区间 \([l,r]\) 中所有矩阵从左到右乘起来的结果

对于能快速合并的信息我们都可以用线段树来维护

比如和,积,最值, 矩阵乘法, bitset, hash值,线性基

还需要一个矩阵的结论:

对于 3*3 的 0/1 矩阵来说 两矩阵的第一二行交换,他们的乘积的第一二行也交换

所以可以对于交换的区间打 tag,用线段树维护

本题思路

考虑本质不同的子序列怎么求:

设 f(i,0) 表示i号位置以前的以0结尾的本质不同的子序列数目

设 f(i,1) 表示i号位置以前的以1结尾的本质不同的子序列数目

转移方程 :

如果 i 号位置是 0 ,\(f(i,0) = f(i-1,0) + f(i-1,1) + 1 ; f(i, 1) = f(i-1, 1)\)

如果 i 号位置是 1 ,\(f(i,1) = f(i-1,0) + f(i-1,1) + 1 ; f(i, 0) = f(i-1, 0)\)

用矩阵加速,可得:

观察矩阵可得,对区间内序列取反,可以转化为把矩阵的前两行,前两列交换

可用线段树来维护

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
#define lson l, mid, rt<<1
#define rson mid+1, r, rt<<1|1
using namespace std;
const int MOD = 1e9 + 7;
int init() {
int rv = 0, fh = 1;
char c = getchar();
while(c <'0' || c > '9') {
if(c == '-') fh = -1;
c=getchar();
}
while(c >= '0' && c <= '9') {
rv=(rv<<1) + (rv<<3) + c- '0';
c = getchar();
}
return fh * rv;
}
const int MAXN=100005;
struct Matrix{
ll num[3][3];
int col;
Matrix() {
col = 0;
memset(num,0,sizeof(num));
}
void build(bool f){
col=3;
if(f) {
num[0][0] = num[0][1] = num[1][1] = num[2][1] = num[2][2] = 1;
}else {
num[0][0] = num[1][0] = num[2][0] = num[1][1] = num[2][2] = 1;
}
}
Matrix operator * (const Matrix &a) {
Matrix ans;
ans.col = col;
for(int i = 0 ; i < col ; i++) {
for(int j = 0 ; j < 3 ; j++) {
for(int k = 0 ; k < 3 ; k++) {
(ans.num[i][j] += num[i][k] * a.num[k][j]) %= MOD;
}
}
}
return ans;
}
void reserve() {
for(int i = 0 ; i < 3 ; i++) {
swap(num[0][i],num[1][i]);
}
for(int i = 0 ; i <3 ; i++) {
swap(num[i][0], num[i][1]);
}
}
void print() {
for(int i = 0 ; i<=col ;i++) {
for(int j = 0 ; j < 3 ; j++) {
printf("%d ",num[i][j]);
}
cout<<endl;
}
}
};
struct SGT{
Matrix sum[MAXN<<2];
bool tag[MAXN<<2];
void PushUp(int rt) {
sum[rt] = sum[rt<<1] * sum[rt<<1|1];
}
void build(int l, int r,int rt) {
if(l==r) {
bool f=init();
sum[rt].build(f);
return;
}
int mid = (l + r) >>1;
build(lson);
build(rson);
PushUp(rt);
}
void PushDown(int rt) {
if(tag[rt]) {
tag[rt<<1] = !tag[rt<<1] ;
tag[rt<<1|1] = !tag[rt<<1|1];
sum[rt<<1].reserve();
sum[rt<<1|1].reserve();
tag[rt]=0;
}
}
void Update(int L, int R, int l, int r, int rt) {
if(L <= l && r <= R) {
tag[rt]=!tag[rt];
sum[rt].reserve();
return;
}
PushDown(rt);
int mid = (l + r) >>1;
if(L <= mid) Update(L, R, lson);
if(mid < R) Update(L, R, rson);
PushUp(rt);
}
Matrix Query(int L, int R, int l, int r, int rt) {
if(L <= l && r <= R) {
return sum[rt];
}
PushDown(rt);
int mid = (l + r) >>1;
Matrix ans;
ans.col = 3;
ans.num[0][0] = ans.num[1][1] = ans.num[2][2] = 1;//ans.print();
if(L <= mid) ans = ans * Query(L, R, lson);
if(mid < R) ans = ans * Query(L, R, rson);
PushUp(rt);
return ans;
}
}sgt;
int n,m;
int main() {
freopen("in.txt", "r", stdin);
n=init();m=init();
sgt.build(1,n,1);
for(int i = 1 ; i <= m ; i++) {
int t = init(), l = init(), r = init();
if(t == 1) {
sgt.Update(l, r, 1, n, 1);
}else {
Matrix ans;
ans.col = 1;ans.num[0][2] = 1;
ans = ans * sgt.Query(l, r, 1, n, 1);
//sgt.Query(l, r, 1, n, 1).print();
printf("%lld\n",(ans.num[0][0] + ans.num[0][1])%MOD);
}
}
fclose(stdin);
return 0;
}

洛谷 [T21776] 子序列的更多相关文章

  1. 洛谷T21776 子序列

    题目描述 你有一个长度为 nn 的数列 \{a_n\}{an​} ,这个数列由 0,10,1 组成,进行 mm 个的操作: 1~l~r1 l r :把数列区间 [l, r][l,r] 内的所有数取反. ...

  2. 洛谷P1410 子序列

    题目描述 给定一个长度为N(N为偶数)的序列,问能否将其划分为两个长度为N/2的严格递增子序列, 输入输出格式 输入格式: 若干行,每行表示一组数据.对于每组数据,首先输入一个整数N,表示序列的长度. ...

  3. 洛谷 P1410 子序列(DP)

    这题的题解的贪心都是错误的...正解应该是个DP 考虑有哪些有关的条件:两个序列的当前长度, 两个序列的末尾数, 把这些都压进状态显然是会GG的 考虑两个长度加起来那一位的数一定是其中一个序列的末尾, ...

  4. 洛谷 P1439 【模板】最长公共子序列

    \[传送门啦\] 题目描述 给出\(1-n\)的两个排列\(P1\)和\(P2\),求它们的最长公共子序列. 输入输出格式 输入格式: 第一行是一个数\(n\), 接下来两行,每行为\(n\)个数,为 ...

  5. 洛谷CF264D Colorful Stones(子序列匹配,思维)

    洛谷题目传送门 神仙思维题. 对于两个字符串的匹配问题,似乎之前蒟蒻写的HAOI2010最长公共子序列题解中提到的建网格图模型是一种套路? 给一个稍微强一点的样例(把字母换成了ABC) AABCB B ...

  6. 洛谷P2516 [HAOI2010]最长公共子序列(LCS,最短路)

    洛谷题目传送门 一进来就看到一个多月前秒了此题的ysn和YCB%%% 最长公共子序列的\(O(n^2)\)的求解,Dalao们想必都很熟悉了吧!不过蒟蒻突然发现,用网格图貌似可以很轻松地理解这个东东? ...

  7. 洛谷1439:最长公共子序列(nlogn做法)

    洛谷1439:最长公共子序列(nlogn做法) 题目描述: 给定两个序列求最长公共子序列. 这两个序列一定是\(1\)~\(n\)的全排列. 数据范围: \(1\leq n\leq 10^5\) 思路 ...

  8. 最长公共子序列问题(LCS) 洛谷 P1439

    题目:P1439 [模板]最长公共子序列 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 关于LCS问题,可以通过离散化转换为LIS问题,于是就可以使用STL二分的方法O(nlogn ...

  9. 洛谷P4608 [FJOI2016]所有公共子序列问题 【序列自动机 + dp + 高精】

    题目链接 洛谷P4608 题解 建个序列自动机后 第一问暴搜 第二问dp + 高精 设\(f[i][j]\)为两个序列自动机分别走到\(i\)和\(j\)节点的方案数,答案就是\(f[0][0]\) ...

随机推荐

  1. ubuntu 14.04 安装tomcat服务器 配置图片路径和文件路径

    root@hett-PowerEdge-T30:/usr/local/src# lltotal 235956drwxr-xr-x  6 root root      4096  3月 26 14:48 ...

  2. Codeforces Round #318 (Div. 2) C Bear and Poker (数学)

    简单题,求一下所有数的2和3的幂是任意调整的,把2和3的因子除掉以后必须相等. 求lcm,爆了long long.我得好好反省一下,对连乘不敏感 #include<bits/stdc++.h&g ...

  3. UVA821 PageHopping (Floyd)

    求所有点直接的平均最短距离,保存一下出现过的点,题目保证是所有点连通,Floyd求出最短路以后两个for统计一下. #include<bits/stdc++.h> using namesp ...

  4. java在线聊天项目0.6版 解决客户端关闭后异常问题 dis.readUTF()循环读取已关闭的socket

    服务端对try catch finally重新进行了定义,当发生异常,主动提示,或关闭出现异常的socket 服务器端代码修改如下: package com.swift; import java.io ...

  5. 121. Best Time to Buy and Sell Stock@python

    Say you have an array for which the ith element is the price of a given stock on day i. If you were ...

  6. JavaScript设计模式基础之闭包(终)

    对于前端程序员来说闭包还是比较难以理解的, 闭包的形成与变量的作用域以及变量的生产周期密切相关,所以要先弄懂变量的作用域和生存周期. 1.变量作用域 变量的作用域,就是指变量的有效范围,通常我们指的作 ...

  7. PHP 线上项目 无法操作

    部署到线上的项目,http 环境没有问题,首页展示没有问题,但是跳转页面展示到了本地, 解决办法 : 更改文件夹所属用户 chown -R apache:apache html

  8. 009 CSS选择器

    CSS选择器 一.基础选择器 1.通配选择器 * { border: solid; } 匹配文档中所有标签:通常指html.body及body中所有显示类的标签 2.标签选择器 div { backg ...

  9. 蓝牙学习(4) -- L2CAP

    L2CAP in protocol 首先看一下L2CAP在Bluetooth protocol architecture diagram中的位置: Features of L2CAP Logical ...

  10. RN与现有的原生app集成

    https://facebook.github.io/react-native/docs/integration-with-existing-apps.html RN可以很好地支持往一个原生的app上 ...