洛谷P3328(bzoj 4085)毒瘤线段树
题面及大致思路: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)毒瘤线段树的更多相关文章
- 洛谷 P3373 【模板】线段树 2
洛谷 P3373 [模板]线段树 2 洛谷传送门 题目描述 如题,已知一个数列,你需要进行下面三种操作: 将某区间每一个数乘上 xx 将某区间每一个数加上 xx 求出某区间每一个数的和 输入格式 第一 ...
- 洛谷P4891 序列(势能线段树)
洛谷题目传送门 闲话 考场上一眼看出这是个毒瘤线段树准备杠题,发现实在太难调了,被各路神犇虐哭qwq 考后看到各种优雅的暴力AC......宝宝心里苦qwq 思路分析 题面里面是一堆乱七八糟的限制和性 ...
- Bzoj5294/洛谷P4428 [Bjoi2018]二进制(线段树)
题面 Bzoj 洛谷 题解 考虑一个什么样的区间满足重组之后可以变成\(3\)的倍数.不妨设\(tot\)为一个区间内\(1\)的个数.如果\(tot\)是个偶数,则这个区间一定是\(3\)的倍数,接 ...
- 洛谷P3372 【模板】线段树 1
P3372 [模板]线段树 1 153通过 525提交 题目提供者HansBug 标签 难度普及+/提高 提交 讨论 题解 最新讨论 [模板]线段树1(AAAAAAAAA- [模板]线段树1 洛谷 ...
- 洛谷 P2574 XOR的艺术(线段树 区间异或 区间求和)
To 洛谷.2574 XOR的艺术 题目描述 AKN觉得第一题太水了,不屑于写第一题,所以他又玩起了新的游戏.在游戏中,他发现,这个游戏的伤害计算有一个规律,规律如下 1. 拥有一个伤害串为长度为n的 ...
- 洛谷P4344 脑洞治疗仪 [SHOI2015] 线段树+二分答案/分块
!!!一道巨恶心的数据结构题,做完当场爆炸:) 首先,如果你用位运算的时候不小心<<打成>>了,你就可以像我一样陷入疯狂的死循环改半个小时 然后,如果你改出来之后忘记把陷入死循 ...
- 【题解】洛谷P1198 [JSOI2008] 最大数(线段树)
洛谷P1198:https://www.luogu.org/problemnew/show/P1198 思路 一道水水的线段树 20分钟A掉 这道题只涉及到单点修改和区间查询 所以这道题甚至不用Laz ...
- bzoj3064/洛谷P4314 CPU监控【线段树】
好,长草博客被催更了[?] 我感觉这题完全可以当作线段树3 线段树2考加法和乘法标记的下放顺序,这道题更丧心病狂[?] 很多人可能跟我一样,刚看到这道题秒出思路:打一个当前最大值一个历史最大值不就完事 ...
- [BZOJ5286][洛谷P4425][HNOI2018]转盘(线段树)
5286: [Hnoi2018]转盘 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 15 Solved: 11[Submit][Status][Di ...
- 洛谷P3373 【模板】线段树 2
P3373 [模板]线段树 2 47通过 186提交 题目提供者HansBug 标签 难度提高+/省选- 提交 讨论 题解 最新讨论 为啥WA(TAT) 题目描述 如题,已知一个数列,你需要进行 ...
随机推荐
- CodeForces 444C 线段树
想分块想了很久一点思路都没有,结果一看都是写的线段树= = ...完全忘记了还有线段树这种操作 题意:给一个数组,一种操作是改变l到r为c,还有一种操作是查询l到r的总和差 线段树记得+lazy标记 ...
- java之 Timer 类的简单使用案例
(如果您看到本文章务必看结尾!) 第一次用Timer类,记录一下个人理解. 场景:做苹果内容结果验证时,根据苹果支付凭证去苹果官方服务器验证是否支付成功.但因为苹果服务器比较慢,第 ...
- 用css方法 可以实现多行 超出宽度 出点点点号
overflow: hidden; -webkit-line-clamp: 2; display: -webkit-box; -webkit-box-orient: vertical;
- 在Java中定义常量
方法一采用接口(Interface)的中变量默认为static final的特性. 方法二采用了Java 5.0中引入的Enum类型. 方法三采用了在普通类中使用static final修饰变量的方法 ...
- 简单常用sql查询
[self.db executeUpdate:sql, record.recordID]; CREATE TABLE scene_record(id TEXT PRIMARY KEY, record_ ...
- hadoop-hive学习笔记
create table hive_1(id string,name string ,gender string)row format delimited fields terminated by ' ...
- 学习动态性能表(6)--v$session_wait&v$session_event
学习动态性能表 第六篇-(1)-V$SESSION_WAIT 2007.5.30 这是一个寻找性能瓶颈的关键视图.它提供了任何情况下session在数据库中当前正在等待什么(如果session当前什 ...
- [转]JavaScript之引用类型
Object类型 Object类型是JavaScript中使用最多的一种类型.虽然Object的实例不具备多少功能,但对于在应用程序中存储和传输数据而言,它确实是非常理想的选择. 创建Object实例 ...
- H5移动端下html上传图片被旋转问题
iOS下,html方式使用<input type="file">上传图片,图片会被旋转.遇到这个问题js是无法解决的,html也没有相应的解决方案.只能放到后台去处理, ...
- Bug:DataGridCell的显示不完整
最近在使用DataGrid时遇到一个bug, 在客户机器上DataGrid的内容显示不完整, 具体表现为某些列的显示为空. 具体的可视树为:DataGridCell > ContentPrese ...