【SDOI2015】【BZOJ4085】音质检测quality

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]);
        }
    }
}

你可能感兴趣的:(随便搞搞,丧心病狂)