bzoj 4085: [Sdoi2015]音质检测
来源:互联网 发布:linux设置定时重启 编辑:程序博客网 时间:2024/04/28 23:45
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4085
思路:
这题我做的好麻烦啊。。。
一开始想分块来着,后来发现可以直接线段树
首先考虑一个性质,我们如果有数列的相邻两项
说实话网上有些做法感觉很不科学啊。。。
比如很多人初始化线段树的时候都暴力求的
复杂度:
代码:
#include<iostream>#include<cstring>#include<string>#include<cstdio>#include<cmath> #define N 300002#define M 50002using 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;}
0 0
- bzoj 4085: [Sdoi2015]音质检测
- 【SDOI2015】【BZOJ4085】音质检测quality
- 【BZOJ 3990】 [SDOI2015]排序
- BZOJ 3990: [SDOI2015]排序
- 【BZOJ 3990】 [SDOI2015]排序
- BZOJ 3990 [SDOI2015] 排序
- BZOJ 3990 Sdoi2015 排序 DFS
- bzoj 3993: [Sdoi2015]星际战争
- BZOJ 3993 [SDOI2015]星际战争
- BZOJ 3991: [SDOI2015]寻宝游戏
- 【BZOJ 3991】 [SDOI2015]寻宝游戏
- 【BZOJ 3993】 [SDOI2015]星际战争
- BZOJ 3991: [SDOI2015]寻宝游戏
- BZOJ 3992 SDOI2015 序列统计
- BZOJ 3995 SDOI2015 道路修建
- BZOJ 3991 [SDOI2015]寻宝游戏
- BZOJ 3995: [SDOI2015]道路修建
- BZOJ 3992 [SDOI2015]序列统计
- 自组织映射网络
- url中的参数加密
- EM算法(生)
- 数字三角形问题
- linux copy_from/to_user原理
- bzoj 4085: [Sdoi2015]音质检测
- 云计算学习,OpenStack主要逻辑模块Nova的详细功能
- 前端小白训练营DAY3
- 【UGUI】屏幕区域点击检测
- 排序
- SATA盘和SAS盘区别
- 判断链表序列是否对称
- 文章标题
- hdu1074Doing Homework( 状态压缩dp)