题面及大致思路:https://www.cnblogs.com/Yangrui-Blog/p/9623294.html, https://www.cnblogs.com/New-Godess/p/4567282.html

每个点维护2个矩阵,一共15个变量。矩阵a: [a(i - 1), a(i), a(i + 1); b(i - 1), b(i), b(i + 1)], 矩阵b就是a(i - 1), a(i), a(i + 1)与b(i - 1), b(i), b(i + 1)的两两乘积,矩阵转移的过程很显然,就不细说了。这个题的思维难度不高,就是两点很烦人:1 卡常 2 维护变量很麻烦。

代码:

#include <bits/stdc++.h>
#define ls(x) (x << 1)
#define rs(x) ((x << 1) | 1)
using namespace std;
const int mod = 1000000007;
const int maxn = 300010;
int c[maxn][4];
int a, b, inv;
int qpow(int x, int y) {
int ans = 1;
for(; y; y >>= 1) {
if(y & 1) ans = 1ll * ans * x % mod;
x = 1ll * x * x % mod;
}
return ans;
}
struct Matrix {
int a[3][3], n, m;
void init(int x) {
memset(a, 0, sizeof(a));
n = m = x;
for (int i = 0; i < n; i++) a[i][i] = 1;
}
Matrix operator * (const Matrix &rhs) const {
Matrix ret; memset(ret.a, 0, sizeof(ret.a));
ret.n = n, ret.m = rhs.m;
for (int i = 0; i < n; i++)
for (int k = 0; k < m; k++)
for (int j = 0; j < 2; j++)
ret.a[i][j] = (ret.a[i][j] + 1ll * a[i][k] * rhs.a[k][j] % mod) % mod;
ret.a[2][2] = 1;
return ret;
}
};
Matrix A, B, p[35], E;
Matrix qpow(int k) {
Matrix ans = E;
for (int i = 1; k; i++, k >>= 1) {
if(k & 1) ans = ans * p[i];
}
return ans;
}
void get_Matrix(int pos) {
Matrix tmp = A * qpow(c[pos][0] - 2);
c[pos][1] = tmp.a[0][1], c[pos][2] = tmp.a[0][0];
}
void init_p() {
A.n = 1, A.m = 3;
A.a[0][0] = 2, A.a[0][1] = 1, A.a[0][2] = 1;
B.n = B.m = 3;
B.a[0][0] = 1; B.a[1][0] = a, B.a[2][0] = b;
B.a[0][1] = 1; B.a[2][2] = 1;
for (int i = 1; i <= 32; i++) {
p[i] = B;
B = B * B;
}
}
struct SegementTree {
int sum[2][3], val[3][3], l, r, lz[2];
};
SegementTree tr[maxn * 4];
inline void pushup(int now) {
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
tr[now].val[i][j] = (tr[ls(now)].val[i][j] + tr[rs(now)].val[i][j]) % mod;
for (int i = 0; i < 2; i++)
for (int j = 0; j < 3; j++)
tr[now].sum[i][j] = (tr[ls(now)].sum[i][j] + tr[rs(now)].sum[i][j]) % mod;
}
inline void add1(int now, int flag) {
int l = tr[now].l, r = tr[now].r;
for (int i = 0; i < 2; i++)
tr[now].sum[flag][i] = tr[now].sum[flag][i + 1];
tr[now].sum[flag][2] = (tr[now].sum[flag][1] + 1ll * tr[now].sum[flag][0] * a + 1ll * b * (r - l + 1)) % mod;
if(flag == 0) {
for (int i = 0; i < 2; i++)
for (int j = 0 ; j < 3; j++)
tr[now].val[i][j] = tr[now].val[i + 1][j];
for (int j = 0; j < 3; j++)
tr[now].val[2][j] = (tr[now].val[1][j] + 1ll * tr[now].val[0][j] * a + 1ll * b * tr[now].sum[1][j]) % mod;
} else {
for (int i = 0; i < 3; i++)
for (int j = 0; j < 2; j++)
tr[now].val[i][j] = tr[now].val[i][j + 1];
for (int i = 0; i < 3; i++)
tr[now].val[i][2] = (tr[now].val[i][1] + 1ll * tr[now].val[i][0] * a + 1ll * b * tr[now].sum[0][i]) % mod;
}
}
inline void dec1(int now, int flag) {
int l = tr[now].l, r = tr[now].r;
if(a == 0) {
for (int i = 1; i >= 0; i--) tr[now].sum[flag][i + 1] = tr[now].sum[flag][i];
tr[now].sum[flag][0] = (tr[now].sum[flag][1] - 1ll * b * (r - l + 1) % mod + mod) % mod;
if(flag == 0) {
for (int i = 1; i >= 0; i--)
for (int j = 0; j < 3; j++)
tr[now].val[i + 1][j] = tr[now].val[i][j];
for (int i = 0; i < 3; i++)
tr[now].val[0][i] = (tr[now].val[1][i] - 1ll * b * tr[now].sum[1][i] % mod + mod) % mod;
} else {
for (int i = 0; i < 3; i++)
for (int j = 1; j >= 0; j--)
tr[now].val[i][j + 1] = tr[now].val[i][j];
for (int i = 0; i < 3; i++)
tr[now].val[i][0] = (tr[now].val[i][1] - 1ll * b * tr[now].sum[0][i] % mod + mod) % mod;
}
return;
}
for (int i = 1; i >= 0; i--)
tr[now].sum[flag][i + 1] = tr[now].sum[flag][i];
tr[now].sum[flag][0] = ((tr[now].sum[flag][2] - tr[now].sum[flag][1] - 1ll * b * (r - l + 1) % mod) * inv % mod + mod) % mod;
if(flag == 0) {
for (int i = 1; i >= 0; i--)
for (int j = 0; j < 3; j++)
tr[now].val[i + 1][j] = tr[now].val[i][j];
for (int i = 0; i < 3; i++)
tr[now].val[0][i] = ((tr[now].val[2][i] - tr[now].val[1][i] - 1ll * b * tr[now].sum[1][i] % mod) % mod * inv % mod + mod) % mod;
} else {
for (int i = 0; i < 3; i++)
for (int j = 1; j >= 0; j--)
tr[now].val[i][j + 1] = tr[now].val[i][j];
for (int i = 0; i < 3; i++)
tr[now].val[i][0] = ((tr[now].val[i][2] - tr[now].val[i][1] - 1ll * b * tr[now].sum[0][i] % mod) % mod * inv % mod + mod) % mod;
}
}
inline void pushdown(int now, int flag, int y) {
if(y > 0) for (int i = 1; i <= y; i++) add1(now, flag);
else for (int i = -1; i >= y; i--) dec1(now, flag);
}
inline void Pushdown(int now) {
for (int flag = 0; flag < 2; flag++) {
pushdown(ls(now), flag, tr[now].lz[flag]);
pushdown(rs(now), flag, tr[now].lz[flag]);
tr[ls(now)].lz[flag] += tr[now].lz[flag];
tr[rs(now)].lz[flag] += tr[now].lz[flag];
tr[now].lz[flag] = 0;
}
}
inline void build(int now, int l, int r) {
tr[now].l = l, tr[now].r = r;
if(l == r) {
for (int i = 0; i < 3; i++) {
tr[now].sum[0][i] = c[l - 1][i + 1];
tr[now].sum[1][i] = c[l + 1][i + 1];
}
for (int i = 0; i < 3; i++)
for (int j = 0;j < 3; j++)
tr[now].val[i][j] = 1ll * tr[now].sum[0][i] * tr[now].sum[1][j] % mod;
return;
}
int mid = (l + r) >> 1;
build(ls(now), l, mid);
build(rs(now), mid + 1, r);
pushup(now);
}
inline void update(int now, int ql, int qr, int flag,int val) {
int l = tr[now].l, r = tr[now].r;
if(l > qr || r < ql) return;
if(l >= ql && r <= qr) {
tr[now].lz[flag] += val;
pushdown(now, flag, val);
return;
}
Pushdown(now);
int mid = (l + r) >> 1;
if(ql <= mid) update(ls(now), ql, qr, flag, val);
if(qr > mid) update(rs(now), ql, qr, flag, val);
pushup(now);
}
inline int query(int now, int ql, int qr) {
int l = tr[now].l, r = tr[now].r;
if(l > qr || r < ql) return 0;
if(l >= ql && r <= qr) return tr[now].val[2][0];
Pushdown(now);
int mid = (l + r) >> 1;
int ans = 0;
if(ql <= mid) ans = (ans + query(ls(now), ql, qr)) % mod;
if(qr > mid) ans = (ans + query(rs(now), ql, qr)) % mod;
return ans;
}
int main() {
int n, m;
scanf("%d%d%d%d", &n, &m, &a, &b);
inv = qpow(a, mod - 2);
E.init(3);
init_p();
for (int i = 1; i <= n; i++) {
scanf("%d", &c[i][0]);
get_Matrix(i);
c[i][3] = (c[i][2] + 1ll * a * c[i][1] % mod + b) % mod;
}
char op[10];
build(1, 2, n - 1);
while(m--) {
scanf("%s", op + 1);
int x, y;
scanf("%d%d", &x, &y);
if(op[1] == 'p') {
update(1, x + 1, y + 1, 0, 1);
update(1, x - 1, y - 1, 1, 1);
} else if (op[1] == 'm') {
update(1, x + 1, y + 1, 0, -1);
update(1, x - 1, y - 1, 1, -1);
} else {
printf("%d\n", query(1, x + 1, y - 1));
}
}
}

  

洛谷P3328(bzoj 4085)毒瘤线段树的更多相关文章

  1. 洛谷 P3373 【模板】线段树 2

    洛谷 P3373 [模板]线段树 2 洛谷传送门 题目描述 如题,已知一个数列,你需要进行下面三种操作: 将某区间每一个数乘上 xx 将某区间每一个数加上 xx 求出某区间每一个数的和 输入格式 第一 ...

  2. 洛谷P4891 序列(势能线段树)

    洛谷题目传送门 闲话 考场上一眼看出这是个毒瘤线段树准备杠题,发现实在太难调了,被各路神犇虐哭qwq 考后看到各种优雅的暴力AC......宝宝心里苦qwq 思路分析 题面里面是一堆乱七八糟的限制和性 ...

  3. Bzoj5294/洛谷P4428 [Bjoi2018]二进制(线段树)

    题面 Bzoj 洛谷 题解 考虑一个什么样的区间满足重组之后可以变成\(3\)的倍数.不妨设\(tot\)为一个区间内\(1\)的个数.如果\(tot\)是个偶数,则这个区间一定是\(3\)的倍数,接 ...

  4. 洛谷P3372 【模板】线段树 1

    P3372 [模板]线段树 1 153通过 525提交 题目提供者HansBug 标签 难度普及+/提高 提交  讨论  题解 最新讨论 [模板]线段树1(AAAAAAAAA- [模板]线段树1 洛谷 ...

  5. 洛谷 P2574 XOR的艺术(线段树 区间异或 区间求和)

    To 洛谷.2574 XOR的艺术 题目描述 AKN觉得第一题太水了,不屑于写第一题,所以他又玩起了新的游戏.在游戏中,他发现,这个游戏的伤害计算有一个规律,规律如下 1. 拥有一个伤害串为长度为n的 ...

  6. 洛谷P4344 脑洞治疗仪 [SHOI2015] 线段树+二分答案/分块

    !!!一道巨恶心的数据结构题,做完当场爆炸:) 首先,如果你用位运算的时候不小心<<打成>>了,你就可以像我一样陷入疯狂的死循环改半个小时 然后,如果你改出来之后忘记把陷入死循 ...

  7. 【题解】洛谷P1198 [JSOI2008] 最大数(线段树)

    洛谷P1198:https://www.luogu.org/problemnew/show/P1198 思路 一道水水的线段树 20分钟A掉 这道题只涉及到单点修改和区间查询 所以这道题甚至不用Laz ...

  8. bzoj3064/洛谷P4314 CPU监控【线段树】

    好,长草博客被催更了[?] 我感觉这题完全可以当作线段树3 线段树2考加法和乘法标记的下放顺序,这道题更丧心病狂[?] 很多人可能跟我一样,刚看到这道题秒出思路:打一个当前最大值一个历史最大值不就完事 ...

  9. [BZOJ5286][洛谷P4425][HNOI2018]转盘(线段树)

    5286: [Hnoi2018]转盘 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 15  Solved: 11[Submit][Status][Di ...

  10. 洛谷P3373 【模板】线段树 2

     P3373 [模板]线段树 2 47通过 186提交 题目提供者HansBug 标签 难度提高+/省选- 提交  讨论  题解 最新讨论 为啥WA(TAT) 题目描述 如题,已知一个数列,你需要进行 ...

随机推荐

  1. css3——transition属性和opacity属性

    [transition-duration] 是一个css3属性,规定完成过度效果需要花费的时间(一秒或毫秒计).语法:transition-duration: time;time :    规定完成过 ...

  2. php微信开发之带参数二维码的使用

    最近做微信PC端网页微信相关功能的开发,从一个新手的角度来说,微信公众号的文档还是不好理解的,网上找的帖子大都也都基本上是复制微信公众平台上给的文档,开发微信带参数二维码过程中还是遇到不少坑的,在此把 ...

  3. ural 2022 Riding a Toad

    2022. Riding a Toad Time limit: 1.0 secondMemory limit: 64 MB A tribe of leafmen live in the old for ...

  4. android将drawable下的图片转换成bitmap

    将drawable下的图片转换成bitmap 1. Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.xx ...

  5. 在Android中使用实时调度(real-time)

    Linux的线程调度策略中有FIFO和RT的实时调度方法,但是在Android中做了限制,普通用户不能修改线程的调度算法为FIFO和RT,必须ROOT用户才能更改.但问题是程序是以普通用户启动和运行的 ...

  6. The CHECK_POLICY and CHECK_EXPIRATION options cannot be turned OFF when MUST_CHANGE is ON. (Microsoft SQL Server,错误: 15128)

    记录下 The CHECK_POLICY and CHECK_EXPIRATION options cannot be turned OFF when MUST_CHANGE is ON. (Micr ...

  7. 伯乐在线资讯URL

    伯乐资讯URL # encoding: utf-8 import requests from bs4 import BeautifulSoup import csv import time base_ ...

  8. Git_学习_09_Commit message 和 Change log 编写指南

    一.前言 二.Commit message编写 1.规范 2.用空行分开主题和正文 提交时只执行 git commit,这时就会跳出文本编辑器,让你写多行. git commit 主题和正文分开 每次 ...

  9. Leetcode 970. Powerful Integers

    Brute Force(暴力) class Solution(object): def powerfulIntegers(self, x, y, bound): """ ...

  10. CodeForces - 896D :Nephren Runs a Cinema(卡特兰数&组合数学---比较综合的一道题)

    Lakhesh loves to make movies, so Nephren helps her run a cinema. We may call it No. 68 Cinema. Howev ...