HDU 6155 Subsequence Count dp + 矩阵+ 线段树
来源:互联网 发布:瑟尔效应 知乎 编辑:程序博客网 时间:2024/06/08 05:08
传送门:HDU6155
题意:给出一个长度为n的01串和两种操作:
1.将区间[L, R]翻转(0变1,1变0)
2.计算区间[L, R]的不同的子序列的个数
思路:一开始以为算子串数量,对着题解怼了半天没看懂。。
叉姐的题解:
来自:ICPCCamp
里面帖子的回复中有对转移方程为什么不会重复计数的解释。
然后就是如何用线段树去维护:详细讲解
但是我看了很多的博客都没有讲解为什么翻转以后的矩阵能由翻转前的矩阵行列交换得到,我只能看出来最基础的两个转移矩阵确实满足行列交换后相等的关系。。可能是我太弱了吧。。
然后我就选择了一种更加直白的方式—–线段树每个结点维护两个矩阵,分别对应翻转前后,不过这样时间复杂度和空间复杂度会稍高一点。
代码:
#include<bits/stdc++.h>#define ll long long#define inf 0x3f3f3f3f#define lson l, mid, rt << 1#define rson mid + 1, r, rt << 1 | 1using namespace std;typedef pair<int,int> P;const int MAXN = 100010;const int mod = 1e9 + 7;struct mat{ long long val[3][3]; void init() { memset(val, 0, sizeof val); } friend mat operator * (mat &a, mat &b) { mat c; c.init(); for(int k = 0; k < 3; k++) { for(int i = 0; i < 3; i++) { if(a.val[i][k] == 0) continue; for(int j = 0; j < 3; j++) { c.val[i][j] = (c.val[i][j] + a.val[i][k] * b.val[k][j]) % mod; } } } return c; }};mat a1 = {1, 0, 0, 1, 1, 0, 1, 0, 1}, b1 = {1, 1, 0, 0, 1, 0, 0, 1, 1};bool flip[MAXN << 2];struct Node{ mat a, b;}tree[MAXN << 2];char str[MAXN];void push_up(int rt){ tree[rt].a = tree[rt << 1].a * tree[rt << 1 | 1].a; tree[rt].b = tree[rt << 1].b * tree[rt << 1 | 1].b;}void build(int l, int r, int rt){ flip[rt] = 0; if(l == r) { if(str[l - 1] - '0') { tree[rt].a = b1; tree[rt].b = a1; } else { tree[rt].a = a1; tree[rt].b = b1; } return ; } int mid = (l + r) >> 1; build(lson); build(rson); push_up(rt);}void push_down(int rt){ if(flip[rt]) { swap(tree[rt << 1].a, tree[rt << 1].b); swap(tree[rt << 1 | 1].a, tree[rt << 1 | 1].b); flip[rt << 1] ^= 1; flip[rt << 1 | 1] ^= 1; flip[rt] = 0; }}void update(int L, int R, int l, int r, int rt){ if(L <= l && r <= R) { flip[rt] ^= 1; swap(tree[rt].a, tree[rt].b); return ; } push_down(rt); int mid = (l + r) >> 1; if(L <= mid) update(L, R, lson); if(R > mid) update(L, R, rson); push_up(rt); }mat query(int L, int R, int l, int r, int rt){ if(L <= l && r <= R) return tree[rt].a; push_down(rt); int mid = (l + r) >> 1; mat res = {1, 0, 0, 0, 1, 0, 0, 0, 1}; mat x; if(L <= mid) x = query(L, R, lson), res = res * x; if(R > mid) x = query(L, R, rson), res = res * x; return res;}int main(){ int T, n, q; cin >> T; while(T--) { int tp, l, r; scanf("%d %d", &n, &q); scanf(" %s", str); build(1, n, 1); while(q--) { scanf("%d %d %d", &tp, &l, &r); if(tp == 1) update(l, r, 1, n, 1); else { mat ans = query(l, r, 1, n, 1); printf("%lld\n", (ans.val[2][0] + ans.val[2][1]) % mod); } } } return 0;}
我用的转移方程来自这里。
阅读全文
0 0
- HDU 6155 Subsequence Count dp + 矩阵+ 线段树
- Hdu 6155 Subsequence Count 矩阵计算DP+线段树维护
- HDU 6155 Subsequence Count(线段树 dp)
- HDU 6155 Subsequence Count [线段树维护矩阵]
- hdu6155-Subsequence Count(线段树+矩阵+dp)
- Subsequence Count 2017ccpc网络赛 1006 dp+线段树维护矩阵
- HDU 6155 DP+矩阵+线段树
- HDU 6155 dp+矩阵+线段树
- hdu 6155(线段树+dp+矩阵)
- [HDU 6155] Subsequence Count
- HDU 6155 Subsequence Count
- 【线段树优化dp】zoj3349 Special Subsequence
- Hdu 6155 线段树维护转移矩阵
- Common Subsequence HDU dp
- HDU 3607 线段树+DP
- HDU 3698 DP+线段树
- HDU 3564 线段树+DP
- hdu 4521(dp+线段树)
- POJ 1236 Network of Schools【tarjan算法】【模板题】
- 【luogu1024】一元三次方程求解(精度控制)
- javase面向对象三大特性之继承
- Cookie&Session详解
- 大数据领域的杰出公司(国内外1)
- HDU 6155 Subsequence Count dp + 矩阵+ 线段树
- python使用自己封装的库
- 避免’sudo echo x >’ 时’Permission denied’ 甲: 示例 sudo echo a > 1.txt -bash: 1.txt: Permission denied 乙:
- JAVA正则表达
- redis中conf文件中的配置
- netty(十一)源码分析之ByteBuf 三
- 【树链剖分模板】题
- 【分页查询】Page如何做到分页查询
- linux查找文件以及文件夹命令