4085: [Sdoi2015]quality
Time Limit: 80 Sec Memory Limit: 512 MB
Submit: 79 Solved: 27
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
Sample Output
HINT
Source
题面请去Vijos看.(目前Vijos需要
线段树+矩乘,在线段树里维护了9个量来做…
矩阵构建分2*2和3*3两种方式,这是在rank榜上产生这么大速度差异的主要原因
我写的是3*3的,但是3*3的矩阵有两个位置是没什么用的,可以拿掉来省下一部分时间
为了跑得快,可以预处理2的幂次的矩阵.
挺好理解的,主要是难写…
#include
#include
#include
#include
#include
#define MAXN 300010
#define GET (ch>='0'&&ch<='9')
#define P 1000000007
#define lchild rt<<1,l,mid
#define rchild rt<<1|1,mid+1,r
#define ln rt<<1
#define rn rt<<1|1
using namespace std;
inline void in(int &x)
{
char ch=getchar();x=0;
while (!GET) ch=getchar();
while (GET) x=x*10+ch-'0',ch=getchar();
}
int a,b,inv,f1,f2;
int n,m,v[MAXN*3][4];
char ch[10];
struct matrix
{
int a[3][3];
friend inline matrix operator * (const matrix& A,const matrix& B)
{
matrix ret;
ret.a[0][0]=(1ll*A.a[0][0]*B.a[0][0]+1ll*A.a[0][1]*B.a[1][0])%P;
ret.a[0][1]=(1ll*A.a[0][0]*B.a[0][1]+1ll*A.a[0][1]*B.a[1][1])%P;
ret.a[0][2]=(1ll*A.a[0][0]*B.a[0][2]+1ll*A.a[0][1]*B.a[1][2]+A.a[0][2])%P;
ret.a[1][0]=(1ll*A.a[1][0]*B.a[0][0]+1ll*A.a[1][1]*B.a[1][0])%P;
ret.a[1][1]=(1ll*A.a[1][0]*B.a[0][1]+1ll*A.a[1][1]*B.a[1][1])%P;
ret.a[1][2]=(1ll*A.a[1][0]*B.a[0][2]+1ll*A.a[1][1]*B.a[1][2]+A.a[1][2])%P;
ret.a[2][0]=ret.a[2][1]=0;ret.a[2][2]=1;return ret;
}
}Pow2[64];
inline int Pow(int a,int b)
{
int ret=1;
for (a%=P;b;b>>=1,a=1ll*a*a%P) if (b&1) ret=(1ll*ret*a%P);
return ret;
}
struct Matrix
{
int a[9][9];
Matrix() { memset(a,0,sizeof(a)); }
friend inline Matrix operator * (const Matrix& A,const Matrix& B)
{
static Matrix ret;memset(ret.a,0,sizeof(ret.a));
for (int i=0;i<9;i++) for (int j=0;j<9;j++) for (int k=0;k<9;k++)
{
ret.a[i][j]+=1ll*A.a[i][k]*B.a[k][j]%P;
if (ret.a[i][j]>=P) ret.a[i][j]-=P;
}
return ret;
}
}mat[4][22],I;
inline void calc(int x)
{
if (x==1) { f1=1;f2=2;return; }
static matrix f;f=Pow2[0];x-=2;
for (int i=1;x;x>>=1,i++) if (x&1) f=f*Pow2[i];
f1=(2ll*f.a[1][0]+f.a[1][1]+f.a[1][2])%P;f2=(2ll*f.a[0][0]+f.a[0][1]+f.a[0][2])%P;
}
struct seg
{
int l,r,lflag,rflag,val[9];
inline void init(int fa,int fa_i,int fb,int fb_i)
{
val[0]=1ll*fa*fb%P;val[1]=1ll*fa*fb_i%P;val[2]=1ll*fa_i*fb%P;val[3]=1ll*fa_i*fb_i%P;
val[4]=fa;val[5]=fa_i;val[6]=fb;val[7]=fb_i;val[8]=1;
}
}tree[1048576+10],ans;
void init(int opt,int x,int y,int z)
{
mat[opt][0]=I;
if (opt==0) mat[opt][1].a[0][2]=1,mat[opt][1].a[1][3]=1,mat[opt][1].a[2][0]=y,mat[opt][1].a[2][2]=x,mat[opt][1].a[2][6]=z,
mat[opt][1].a[3][1]=y,mat[opt][1].a[3][3]=x,mat[opt][1].a[3][7]=z,mat[opt][1].a[4][5]=1,mat[opt][1].a[5][4]=y,
mat[opt][1].a[5][5]=x,mat[opt][1].a[5][8]=z,mat[opt][1].a[6][6]=1,mat[opt][1].a[7][7]=1,mat[opt][1].a[8][8]=1;
else
if (opt==1) mat[opt][1].a[0][1]=1,mat[opt][1].a[1][0]=y,mat[opt][1].a[1][1]=x,mat[opt][1].a[1][4]=z,mat[opt][1].a[2][3]=1,
mat[opt][1].a[3][2]=y,mat[opt][1].a[3][3]=x,mat[opt][1].a[3][5]=z,mat[opt][1].a[4][4]=1,mat[opt][1].a[5][5]=1,
mat[opt][1].a[6][7]=1,mat[opt][1].a[7][6]=y,mat[opt][1].a[7][7]=x,mat[opt][1].a[7][8]=z,mat[opt][1].a[8][8]=1;
else
if (opt==2) mat[opt][1].a[0][0]=y,mat[opt][1].a[0][2]=x,mat[opt][1].a[0][6]=z,mat[opt][1].a[1][1]=y,mat[opt][1].a[1][3]=x,
mat[opt][1].a[1][7]=z,mat[opt][1].a[2][0]=1,mat[opt][1].a[3][1]=1,mat[opt][1].a[4][4]=y,mat[opt][1].a[4][5]=x,
mat[opt][1].a[4][8]=z,mat[opt][1].a[5][4]=1,mat[opt][1].a[6][6]=1,mat[opt][1].a[7][7]=1,mat[opt][1].a[8][8]=1;
else
mat[opt][1].a[0][0]=y,mat[opt][1].a[0][1]=x,mat[opt][1].a[0][4]=z,mat[opt][1].a[1][0]=1,mat[opt][1].a[2][2]=y,
mat[opt][1].a[2][3]=x,mat[opt][1].a[2][5]=z,mat[opt][1].a[3][2]=1,mat[opt][1].a[4][4]=1,mat[opt][1].a[5][5]=1,
mat[opt][1].a[6][6]=y,mat[opt][1].a[6][7]=x,mat[opt][1].a[6][8]=z,mat[opt][1].a[7][6]=1,mat[opt][1].a[8][8]=1;
for (int i=2;i<=20;i++) mat[opt][i]=mat[opt][i-1]*mat[opt][i-1];
}
inline void push_up(int rt)
{
for (int i=0;i<9;i++) tree[rt].val[i]=(tree[ln].val[i]+tree[rn].val[i])%P;
}
inline void upd(int rt,Matrix Pw[],int b)
{
for (int i=1;b;b>>=1,i++)
if (b&1)
{
int tmp[9];memset(tmp,0,sizeof(tmp));
for (int j=0;j<9;j++) for (int k=0;k<9;k++)
{
tmp[j]+=1ll*Pw[i].a[j][k]*tree[rt].val[k]%P;
if (tmp[j]>=P) tmp[j]-=P;
}
for (int j=0;j<9;j++) tree[rt].val[j]=tmp[j];
}
}
inline void calc(int rt,int a,int b)
{
if (a!=0) upd(rt,a<0?mat[2]:mat[0],a<0?-a:a);
if (b!=0) upd(rt,b<0?mat[3]:mat[1],b<0?-b:b);
}
inline void push_down(int rt)
{
calc(rt,tree[rt].lflag,tree[rt].rflag);
if (tree[rt].l==tree[rt].r) { tree[rt].lflag=tree[rt].rflag=0;return; }
if (tree[rt].lflag!=0||tree[rt].rflag!=0)
tree[ln].lflag+=tree[rt].lflag,tree[rn].lflag+=tree[rt].lflag,
tree[ln].rflag+=tree[rt].rflag,tree[rn].rflag+=tree[rt].rflag;
tree[rt].lflag=tree[rt].rflag=0;
}
void build(int rt=1,int l=2,int r=n-1)
{
tree[rt].l=l;tree[rt].r=r;
if (l==r) { tree[rt].init(v[l-1][2],v[l-1][3],v[r+1][0],v[r+1][1]);return; }
int mid=(l+r)>>1;build(lchild);build(rchild);push_up(rt);
}
void modify(int rt,int l,int r,int opt)
{
int L=tree[rt].l,R=tree[rt].r,mid=(L+R)>>1;
if (l<=L&&r>=R)
{
if (opt==0) tree[rt].lflag++;
else if (opt==1) tree[rt].rflag++;
else if (opt==2) tree[rt].lflag--;
else tree[rt].rflag--;
return;
}
push_down(rt);
if (r<=mid) modify(ln,l,r,opt);
else if (l>mid) modify(rn,l,r,opt);
else modify(ln,l,mid,opt),modify(rn,mid+1,r,opt);
push_down(ln);push_down(rn);push_up(rt);
}
void Modify(int opt,int l,int r)
{
if (l>r) return;
modify(1,l,r,opt);
}
void query(int rt,int l,int r)
{
push_down(rt);
int L=tree[rt].l,R=tree[rt].r,mid=(L+R)>>1;
if (l<=L&&r>=R)
{
for (int i=0;i<9;i++)
{
ans.val[i]+=tree[rt].val[i];
if (ans.val[i]>=P) ans.val[i]-=P;
}
return;
}
if (r<=mid) query(ln,l,r);
else if (l>mid) query(rn,l,r);
else query(ln,l,mid),query(rn,mid+1,r);
}
int main()
{
in(n);in(m);in(a);in(b);a%=P;b%=P;int u,l,r;inv=Pow(a,P-2);
for (int i=0;i<9;i++) I.a[i][i]=1;
Pow2[0].a[0][0]=Pow2[0].a[1][1]=Pow2[0].a[2][2]=1;
Pow2[1].a[0][0]=Pow2[1].a[1][0]=Pow2[1].a[2][2]=1;
Pow2[1].a[0][1]=a;Pow2[1].a[0][2]=b;
for (int i=2;i<=32;i++) Pow2[i]=Pow2[i-1]*Pow2[i-1];
for (int i=1;i<=n;i++)
in(u),calc(u),
v[i][0]=f1,v[i][1]=f2,
v[i][2]=(1ll*v[i][0]*a+b+v[i][1])%P,
v[i][3]=(1ll*v[i][1]*a+v[i][2]+b)%P;
init(0,1,a,b);init(1,1,a,b);
if (a) init(2,inv,(P-inv)%P,1ll*b*(P-inv)%P),init(3,inv,(P-inv)%P,1ll*b*(P-inv)%P);
else init(2,0,1,(P-b)%P),init(3,0,1,(P-b)%P);
build();
while (m--)
{
scanf("%s",ch+1);in(l);in(r);
if (ch[1]=='p') Modify(0,l+1,min(r+1,n-1)),Modify(1,max(l-1,2),r-1);
if (ch[1]=='m') Modify(2,l+1,min(r+1,n-1)),Modify(3,max(l-1,2),r-1);
if (ch[1]=='q')
{
for (int i=0;i<9;i++) ans.val[i]=0;
if (l+1<=r-1) query(1,l+1,r-1);printf("%d\n",ans.val[0]);
}
}
}