这题我做的好麻烦啊。。。

一开始想分块来着,后来发现可以直接线段树

首先考虑一个性质,我们如果有数列的相邻两项f[i]和 f[i+1]那么用这两项向后推k项其线性表示系数一定(表示为f[i+k]=a∗f[i]+b∗f[i+1]+c的形式),那么这样我们预处理这些系数,注意到维护的是一个乘积的形式,那么我们要维护这个必须得维护8个量,将其写成3 * 3矩阵的形式转移会比较科学,注意a=0的特判。

说实话网上有些做法感觉很不科学啊。。。

比如很多人初始化线段树的时候都暴力求的f函数,感觉不太科学啊。。。我的做法是BSGS预处理矩阵,这样查询单点就从33∗log变为33,不过我跑的好慢啊。。。还有就是标记下传的问题,网上竟然有下传是O(标记数)的做法,感觉和暴力没啥区别。

复杂度:O(Qlogn∗34+Maxval−−−−−−−√∗33)

上code:

#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<cmath>
#define N 300002
#define M 50002
using namespace std;
typedef long long LL;
struct Mat
{
int g[3][3];
}; const int P = 1e9 + 7;
int n,Q,a,b,A[N][4],inva,tag[N << 2],B;
Mat Seg[N << 2];
inline void in(int &x)
{
char c;
while (!isdigit(c = getchar()));
x = (c ^ 48);
while (isdigit(c = getchar())) x = 10 * x + (c ^ 48);
} inline void inc(int &x,int y)
{
x += y;
if (x >= P) x -= P;
} inline void init()
{
in(n); in(Q);
in(a); in(b);
a %= P; b %= P;
for (int i = 1;i <= n; ++i)
in(A[i][2]);
} int coe[M][3],recoe[M][3];
inline int quick(int x,int y)
{
int res = 1,base = x;
for (;y;y >>= 1)
{
if (y & 1) res = 1LL * base * res % P;
base = 1LL * base * base % P;
}
return res;
}
inline void Special()
{
for (int i = 3;i < M - 1; ++i)
{
recoe[i][0] = recoe[i - 1][0];
recoe[i][1] = recoe[i - 1][1];
recoe[i][2] = (recoe[i - 1][2] + P - b) % P;
}
}
inline void Get_Coe()
{
inva = quick(a,P - 2);
coe[0][0] = 0; coe[0][1] = 0; coe[0][2] = 1;
coe[1][0] = 0; coe[1][1] = 1; coe[1][2] = 0;
coe[2][0] = 1; coe[2][1] = 0; coe[2][2] = 0;
for (int i = 3;i < M - 1; ++i)
{
coe[i][0] = (coe[i - 1][0] + 1LL * coe[i - 2][0] * a % P) % P;
coe[i][1] = (coe[i - 1][1] + 1LL * coe[i - 2][1] * a % P) % P;
coe[i][2] = ((coe[i - 1][2] + 1LL * coe[i - 2][2] * a % P) % P + b) % P;
}
recoe[0][0] = 0; recoe[0][1] = 0; recoe[0][2] = 1;
recoe[1][0] = 1; recoe[1][1] = 0; recoe[1][2] = 0;
recoe[2][0] = 0; recoe[2][1] = 1; recoe[2][2] = 0;
if (!a)
{
Special();
return;
}
for (int i = 3;i < M - 1; ++i)
{
recoe[i][0] = 1LL * inva * (( -recoe[i - 1][0] + recoe[i - 2][0] + P) % P) % P;
recoe[i][1] = 1LL * inva * (( -recoe[i - 1][1] + recoe[i - 2][1] + P) % P) % P;
recoe[i][2] = 1LL * inva * ((( -recoe[i - 1][2] + recoe[i - 2][2] + P) % P + P - b) % P) % P;
}
}
inline Mat mul(Mat x,Mat y)
{
Mat c;
memset(c.g,0,sizeof(c.g));
for (int k = 0;k < 3; ++k)
for (int i = 0;i < 3; ++i)
for (int j = 0;j < 3; ++j)
if (x.g[i][k]&&y.g[k][j])
inc(c.g[i][j],1LL * x.g[i][k] * y.g[k][j] % P);
return c;
} Mat Small[M],Big[M];
inline void Mat_init(Mat &x)
{
for (int i = 0;i < 3; ++i)
for (int j = 0;j < 3; ++j)
x.g[i][j] = (i == j);
} inline void BSGS()
{
B = (int)(sqrt(2000000000)) + 5;
Mat now;
now.g[0][0] = 1; now.g[0][1] = 1; now.g[0][2] = 0;
now.g[1][0] = a; now.g[1][1] = 0; now.g[1][2] = 0;
now.g[2][0] = 1; now.g[2][1] = 0; now.g[2][2] = 1;
Mat_init(Small[0]);
for (int i = 1;i <= B; ++i)
Small[i] = mul(Small[i - 1],now);
now = Small[B];
Mat_init(Big[0]);
for (int i = 1;i <= B; ++i)
Big[i] = mul(Big[i - 1],now);
} inline void update(int rt)
{
for (int i = 0;i < 3; ++i)
for (int j = 0;j < 3; ++j)
Seg[rt].g[i][j] = (Seg[rt << 1].g[i][j] + Seg[rt << 1|1].g[i][j]) % P;
} Mat fu;
inline int add_Mul_it(int p,int q)
{
int S = 0;
for (int i = 0;i < 3; ++i)
for (int j = 0;j < 3; ++j)
inc(S,1LL * coe[p][i] * coe[q][j] % P * fu.g[i][j] % P);
return S;
} inline int dec_Mul_it(int p,int q)
{
int S = 0;
for (int i = 0;i < 3; ++i)
for (int j = 0;j < 3; ++j)
inc(S,1LL * recoe[p][i] * recoe[q][j] % P * fu.g[i][j] % P);
return S;
} inline void Deal(int l,int r,int rt,bool kind,int left,int right)
{
fu = Seg[rt];
memset(Seg[rt].g,0,sizeof(Seg[rt].g));
if (!kind)
{
for (int i = 0;i < 3; ++i)
for (int j = 0;j < 3; ++j)
{
int p = (i == 2) ? 0 : (left + 2 - i),q = (j == 2) ? 0 : (right + 2 - j);
Seg[rt].g[i][j] = add_Mul_it(p,q);
}
return;
}
for (int i = 0;i < 3; ++i)
for (int j = 0;j < 3; ++j)
{
int p = (i == 2) ? 0 : (left + i + 1),q = (j == 2) ? 0 : (right + j + 1);
Seg[rt].g[i][j] = dec_Mul_it(p,q);
}
} inline void pushdown(int l,int r,int rt)
{
if (tag[rt])
{
int mid = (r + l) >> 1;
bool pd = (tag[rt] < 0);
int x = (tag[rt] > 0) ? tag[rt] : -tag[rt];
Deal(l,mid,rt << 1,pd,x,x);
Deal(mid + 1,r,rt << 1|1,pd,x,x);
tag[rt << 1] += tag[rt]; tag[rt << 1|1] += tag[rt];
}
tag[rt] = 0;
} inline void build(int l,int r,int rt)
{
int mid = (r + l) >> 1;
tag[rt] = 0;
if (l == r)
{
if (l == 1 || l == n)
{
memset(Seg[rt].g,0,sizeof(Seg[rt].g));
return;
}
for (int i = 0;i < 3; ++i)
for (int j = 0;j < 3; ++j)
{
int p = (i == 2) ? 1 : A[l - 1][3 - i],q = (j == 2) ? 1 : A[l + 1][j ^ 1];
Seg[rt].g[i][j] = 1LL * p * q % P;
}
return;
}
build(l,mid,rt << 1);
build(mid + 1,r,rt << 1|1);
update(rt);
} inline void change(int l,int r,int rt,int ll,int rr,bool kind,int left,int right)
{
int mid = (r + l) >> 1;
if (ll <= l&&rr >= r)
{
Deal(l,r,rt,kind,left,right);
(kind) ? --tag[rt] : ++tag[rt];
return;
}
pushdown(l,r,rt);
if (ll <= mid) change(l,mid,rt << 1,ll,rr,kind,left,right);
if (rr > mid) change(mid + 1,r,rt << 1|1,ll,rr,kind,left,right);
update(rt);
} inline void change1(int l,int r,int rt,int pos,bool kind,int left,int right)
{
if (pos == 1||pos == n) return;
int mid = (r + l) >> 1;
if (l == r)
{
Deal(l,r,rt,kind,left,right);
return;
}
pushdown(l,r,rt);
if (pos <= mid) change1(l,mid,rt << 1,pos,kind,left,right);
if (pos > mid) change1(mid + 1,r,rt << 1|1,pos,kind,left,right);
update(rt);
} inline int query(int l,int r,int rt,int ll,int rr)
{
if (ll > rr) return 0;
int mid = (r + l) >> 1;
if (ll <= l&&rr >= r)
return Seg[rt].g[0][0];
pushdown(l,r,rt);
int SS = 0;
if (ll <= mid) inc(SS,query(l,mid,rt << 1,ll,rr));
if (rr > mid) inc(SS,query(mid + 1,r,rt << 1|1,ll,rr));
update(rt);
return SS;
} inline int Calc(int x)
{
if (x <= 2) return x;
int p = (x - 2) / B,q = (x - 2) % B;
Mat c = mul(Big[p],Small[q]);
int Sum = 0;
inc(Sum,2LL * c.g[0][0] % P);
inc(Sum,c.g[1][0]);
inc(Sum,1LL * b * c.g[2][0] % P);
return Sum;
}
inline void PRE()
{
Get_Coe();
BSGS();
for (int i = 1;i <= n; ++i)
A[i][0] = Calc(A[i][2] - 2),
A[i][1] = Calc(A[i][2] - 1),
A[i][3] = Calc(A[i][2] + 1),
A[i][2] = Calc(A[i][2]);
build(1,n,1);
}
int L,R;
inline void Plus(bool pd)
{
if (R == L)
{
if (L > 1) change1(1,n,1,L - 1,pd,0,1);
if (R < n) change1(1,n,1,R + 1,pd,1,0);
return;
}
if (R - L > 1)
change(1,n,1,L + 1,R - 1,pd,1,1);
change1(1,n,1,L,pd,0,1);
if (L > 1) change1(1,n,1,L - 1,pd,0,1);
change1(1,n,1,R,pd,1,0);
if (R < n) change1(1,n,1,R + 1,pd,1,0);
} inline void QUERY()
{
char ch[10];
for (int i = 1;i <= Q; ++i)
{
scanf("%s",ch);
in(L); in(R);
if (ch[0] == 'p') Plus(0);
if (ch[0] == 'm') Plus(1);
if (ch[0] == 'q')
printf("%d\n",query(1,n,1,L + 1,R - 1));
}
} inline void DO_IT()
{
PRE();
QUERY();
} int main()
{
init();
DO_IT();
return 0;
}

洛谷 P3328 【[SDOI2015]音质检测】的更多相关文章

  1. BZOJ4085: [Sdoi2015]音质检测

    BZOJ4085: [Sdoi2015]音质检测 由于这题太毒了,导致可能会被某些人卡评测,于是成了一道权限题... 本蒟蒻表示没钱氪金... 但是可以去洛谷/Vijos搞搞事... 但是洛谷上只能评 ...

  2. 洛谷P3324 [SDOI2015]星际战争

    题目:洛谷P3324 [SDOI2015]星际战争 思路: 类似<导弹防御塔>,因为题目保证有解,花费时间小于最终答案时一定无法消灭所有敌人,只要花费时间大于等于最终答案都可以消灭所有敌人 ...

  3. LOJ #2185 / 洛谷 P3329 - [SDOI2015]约数个数和(莫比乌斯函数)

    LOJ 题面传送门 / 洛谷题面传送门 题意: 求 \(\sum\limits_{i=1}^n\sum\limits_{j=1}^md(ij)\),\(d(x)\) 为 \(x\) 的约数个数. \( ...

  4. 洛谷P3327 - [SDOI2015]约数个数和

    Portal Description 共\(T(T\leq5\times10^4)\)组数据.给出\(n,m(n,m\leq5\times10^4)\),求\[\sum_{i=1}^n\sum_{j= ...

  5. 洛谷P2251 【质量检测】

    无意中刷st表题看到的题目(抄模板),一看到题目,,,没想用st表,直接莫队?????跑起来也不是特别慢... 这里用flag数组记录出现次数,set维护最小值,用的时候直接取头部. 代码也很短 #i ...

  6. 洛谷P3328(bzoj 4085)毒瘤线段树

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

  7. [洛谷P3321][SDOI2015]序列统计

    题目大意:给你一个集合$n,m,x,S(S_i\in(0,m],m\leqslant 8000,m\in \rm{prime},n\leqslant10^9)$,求一个长度为$n$的序列$Q$,满足$ ...

  8. 洛谷P3327 [SDOI2015]约数个数和(莫比乌斯反演)

    传送门 公式太长了……我就直接抄一下这位大佬好了……实在懒得打了 首先据说$d(ij)$有个性质$$d(ij)=\sum_{x|i}\sum_{y|j}[gcd(x,y)=1]$$ 我们所求的答案为$ ...

  9. 洛谷P3327 [SDOI2015]约数个数和 【莫比乌斯反演】

    题目 设d(x)为x的约数个数,给定N.M,求\(\sum_{i = 1}^{N} \sum_{j = 1}^{M} d(ij)\) 输入格式 输入文件包含多组测试数据.第一行,一个整数T,表示测试数 ...

随机推荐

  1. NOIp知识集合 By cellur925

    基本算法 快速幂 ll ksm(ll a,ll b) { ll ans=; while(b) { ) ans=ans*a%p; b>>=; a=a*a%p; } return ans; } ...

  2. hp惠普工作站 安装ESXI 从U盘启动黑屏问题

    [背景] 公司新买了一套hp z238 workstation需要安装esxi,我按照以前的方法制作好U盘后插入从U盘引导,显示屏一直黑屏,这个问题困扰了我一天....在网上找了好久无果 第二天终于在 ...

  3. The database could not be exclusively locked to perform the operation(SQL Server 5030错误解决办法)(转)

    Microsoft SQL Server 5030错误解决办法 今天在使用SQL Server时,由于之前创建数据库忘记了设置Collocation,数据库中插入中文字符都是乱码,于是到DataBas ...

  4. Python基本的数据类型(补发)

    python基本的数据类型   一.python的基本数据类型 int => 整数,主要用来进行数学运算 str ==> 字符串 可以用来保存少量数据并进行相应操作 bool ==> ...

  5. 去掉word文档两边的空白

    1.设置-页面布局-页边距,把左边距和右边距的数据设置到最小就好,一般为0.43CM 2.把WORD页面顶部标尺,左右拉到最底,如图: 3.在打印预览里,设置页边距,操作方法同 上述 1,如图:

  6. 关于74HC4051的逻辑真值表及延时的重要性/在AD测量中的校准

    一 关于74HC4051: 在/E=0使能输出的条件下,S2S1S0的三个值,能选通Y0~Y7其中的一个通道从Z输出. 二:问题提出:在按照IC给出的真值表进行芯片操作时,输出逻辑完全对不上 三:分析 ...

  7. HDU 1260 Tickets DP

    http://acm.hdu.edu.cn/showproblem.php?pid=1260 用dp[i]表示处理到第i个的时候用时最短. 那么每一个新的i,有两个选择,第一个就是自己不和前面的组队, ...

  8. T-SQL多个小计+合计,分类汇总

    select then '合计' else cast(姓名 as varchar) end 姓名, then '姓名小计' else cast(学期 as varchar) end 学期, case ...

  9. [原]Maven项目编译后classes文件中没有.xml问题

    在做spring+mybatiss时,自动扫描都配置正确了,却在运行时出现了如下错误.后来查看target/classes/.../dao/文件夹下,发现只有mapper的class文件,而没有xml ...

  10. MVC 路由URL重写

    在现今搜索引擎制霸天下的时代,我们不得不做一些东西来讨好爬虫,进而提示网站的排名来博得一个看得过去的流量. URL重写与优化就是搜索引擎优化的手段之一. 假如某手机网站(基于ASP.NET MVC)分 ...