HDU 6155 Subsequence Count(矩阵 + DP + 线段树)题解

左手的ㄟ右手 2021-11-05 02:04 392阅读 0赞

题意:01串,操作1:把l r区间的0变1,1变0;操作2:求出l r区间的子序列种数

思路:设DP[i][j]为到i为止以j结尾的种数,假设j为0,那么dp[i][0] = dp[i - 1][1] + dp[i -1][0] (0结尾新串) + dp[i - 1][0] (0结尾旧串) - dp[i - 1][0] (重复) + 1(0本身被重复时去除)。

那么可以得到转移时的矩阵

\left( \begin{matrix} dp[i - 1][0] & dp[i - 1][1] & 1 \\ 0 & 0 & 0 \\ 0 & 0 & 0 \end{matrix} \right) * \left( \begin{matrix} 1 & 0 & 0 \\ 1 &1 & 0 \\ 1 & 0 & 1 \end{matrix} \right) = \left( \begin{matrix} dp[i][0] & dp[i][1] & 1 \\ 0 & 0 & 0 \\ 0 & 0 & 0 \end{matrix} \right)

那么我们只要用线段树维护连续的矩阵乘积就行了。

如果翻转,那么存在一个规律,可以打表找出,直接实现连续区间矩阵乘积的翻转。

代码:

  1. #include<cmath>
  2. #include<set>
  3. #include<map>
  4. #include<queue>
  5. #include<cstdio>
  6. #include<vector>
  7. #include<cstring>
  8. #include <iostream>
  9. #include<algorithm>
  10. using namespace std;
  11. typedef long long ll;
  12. typedef unsigned long long ull;
  13. const int maxn = 1e5 + 5;
  14. const int M = 50 + 5;
  15. const ull seed = 131;
  16. const int INF = 0x3f3f3f3f;
  17. const ll MOD = 1000000007;
  18. char str[maxn];
  19. struct Mat{
  20. ll s[3][3];
  21. void init(){
  22. memset(s, 0, sizeof(s));
  23. }
  24. };
  25. Mat Mamul(Mat a, Mat b){
  26. Mat ret;
  27. ret.init();
  28. for(int i = 0; i < 3; i++){
  29. for(int j = 0; j < 3; j++){
  30. for(int k = 0; k < 3; k++){
  31. ret.s[i][j] = (ret.s[i][j] + a.s[i][k] * b.s[k][j]) % MOD;
  32. }
  33. }
  34. }
  35. return ret;
  36. }
  37. Mat mul[maxn << 2];
  38. int lazy[maxn << 2];
  39. void is(Mat &a, char s){
  40. if(s == '0'){
  41. a.s[0][0] = 1, a.s[0][1] = 0, a.s[0][2] = 0;
  42. a.s[1][0] = 1, a.s[1][1] = 1, a.s[1][2] = 0;
  43. a.s[2][0] = 1, a.s[2][1] = 0, a.s[2][2] = 1;
  44. }
  45. else{
  46. a.s[0][0] = 1, a.s[0][1] = 1, a.s[0][2] = 0;
  47. a.s[1][0] = 0, a.s[1][1] = 1, a.s[1][2] = 0;
  48. a.s[2][0] = 0, a.s[2][1] = 1, a.s[2][2] = 1;
  49. }
  50. }
  51. void change(Mat &a){
  52. swap(a.s[0][0], a.s[1][1]);
  53. swap(a.s[1][0], a.s[0][1]);
  54. swap(a.s[2][0], a.s[2][1]);
  55. }
  56. void pushdown(int rt){
  57. if(lazy[rt]){
  58. lazy[rt << 1] ^= lazy[rt];
  59. lazy[rt << 1 | 1] ^= lazy[rt];
  60. change(mul[rt << 1]);
  61. change(mul[rt << 1 | 1]);
  62. lazy[rt] = 0;
  63. }
  64. }
  65. void pushup(int rt){
  66. mul[rt] = Mamul(mul[rt << 1], mul[rt << 1 | 1]);
  67. }
  68. void build(int l, int r, int rt){
  69. lazy[rt] = 0;
  70. if(l == r){
  71. is(mul[rt], str[l]);
  72. return;
  73. }
  74. int m = (l + r) >> 1;
  75. build(l, m, rt << 1);
  76. build(m + 1, r, rt << 1 | 1);
  77. pushup(rt);
  78. }
  79. void update(int L, int R, int l, int r, int rt){
  80. if(L <= l && R >= r){
  81. lazy[rt] ^= 1;
  82. change(mul[rt]);
  83. return;
  84. }
  85. pushdown(rt);
  86. int m = (l + r) >> 1;
  87. if(L <= m)
  88. update(L, R, l, m, rt << 1);
  89. if(R > m)
  90. update(L, R, m + 1, r, rt << 1 | 1);
  91. pushup(rt);
  92. }
  93. Mat query(int L, int R, int l, int r, int rt){
  94. if(L <= l && R >= r){
  95. return mul[rt];
  96. }
  97. pushdown(rt);
  98. int m = (l + r) >> 1;
  99. Mat ret;
  100. ret.init();
  101. for(int i = 0; i < 3; i++)
  102. ret.s[i][i] = 1;
  103. if(L <= m)
  104. ret = Mamul(ret, query(L, R, l, m, rt << 1));
  105. if(R > m)
  106. ret = Mamul(ret, query(L, R, m + 1, r, rt << 1 | 1));
  107. pushup(rt);
  108. return ret;
  109. }
  110. int main(){
  111. // Mat a, b;
  112. // is(a, '0'), is(b, '1');
  113. // a = Mamul(Mamul(Mamul(a, b), b), b);
  114. // for(int i = 0; i < 3; i++){
  115. // for(int j = 0; j < 3; j++){
  116. // printf("%d ", a.s[i][j]);
  117. // }
  118. // puts("");
  119. // }
  120. // printf("\n\n\n\n");
  121. //
  122. // is(a, '1'), is(b, '0');
  123. // a = Mamul(Mamul(Mamul(a, b), b), b);
  124. // for(int i = 0; i < 3; i++){
  125. // for(int j = 0; j < 3; j++){
  126. // printf("%d ", a.s[i][j]);
  127. // }
  128. // puts("");
  129. // }
  130. // printf("\n\n\n\n");
  131. int T;
  132. scanf("%d", &T);
  133. while(T--){
  134. int n, q;
  135. scanf("%d%d", &n, &q);
  136. scanf("%s", str + 1);
  137. build(1, n, 1);
  138. while(q--){
  139. int op, l, r;
  140. scanf("%d%d%d", &op, &l, &r);
  141. if(op == 1){
  142. update(l, r, 1, n, 1);
  143. }
  144. else{
  145. Mat a;
  146. a.init();
  147. a.s[0][2] = 1;
  148. a = Mamul(a, query(l, r, 1, n, 1));
  149. ll ans = (a.s[0][0] + a.s[0][1]) % MOD;
  150. printf("%lld\n", ans);
  151. }
  152. }
  153. }
  154. return 0;
  155. }

转载于:https://www.cnblogs.com/KirinSB/p/11215317.html

发表评论

表情:
评论列表 (有 0 条评论,392人围观)

还没有评论,来说两句吧...

相关阅读