【SDOI2015】【BZOJ4085】音质检测quality

来源:互联网 发布:jupyter notebook编程 编辑:程序博客网 时间:2024/04/28 04:21

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<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#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|1using 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]);        }    }}
1 0