CCNU 校赛J---分桶法

题意如上,标程是线段树,每个节点维护  a方的和,b方的和,ab的和,修改就是矩阵乘法,当然区间修改还要lazy标记。。

这里考虑一个思维含量较低的分块做法。。

平方分割法的复杂度为O(n*n^1/2),是要比线段树复杂度高的,但是由于分块做法一般常数小,所以如果不是时间限制卡的很紧,很多题是可以水过去的。

对于这道题目,最大的问题就是区间修改,我们可以仿照线段树里面的lazy思想对于每一个块加一个lazy标记,当我们要修改一个块的时候,如果它是lazy的就把他整个更新一遍就行了,这样子复杂度不变也保证了正确性。

没块维护∑a^2,∑b^2,∑ab,还有一个lazy标记和2*2的变化矩阵(实现lazy思想)

接下来就是普通的分块做法了,每次修改  左-中-右  分别修改,查询同理,注意lazy的使用。

PS。这题我写的很残疾。。要跑1.5秒。。标程1s,据说现场过题的队伍的分块比标程跑的都快,继续加油吧,蒟蒻!

PPS。我知道为什么残疾了,多亏雕爷指导,其实这个取模有深意,直接unsigned int就不用取模了(计组没学好),省去很多时间。。这样跑得就比标程快了。。

<pre name="code" class="cpp">#include <iostream>
#include <stdio.h>
#include <cstring>
#include <cmath>
using namespace std;
int n,m;
unsigned int  a[100005];
unsigned int  b[100005];

int big;
unsigned int ss,x,y,p,q,r,s;

unsigned int  a2[600];
unsigned int  b2[600];
unsigned int  ab[600];
bool flag[600];
unsigned int  ch[600][2][2];

void init(){

    for(int i=0;i<n;i++){
        a2[i/big]=a2[i/big]+a[i]*a[i] ;
        b2[i/big]=b2[i/big]+b[i]*b[i] ;
        ab[i/big]=ab[i/big]+a[i]*b[i] ;
    }
    for(int i=0;i<600;i++){
        ch[i][0][0]=1;ch[i][0][1]=0;
        ch[i][1][0]=0;ch[i][1][1]=1;
    }
}
unsigned int t1,t2,t3,tmp1,tmp2,ret;
int L,R;
unsigned int va1,va2,va3,va4;
int fn;

void update(){
    L=x/big,R=y/big;
    if(R==L){
        if(flag[L]){
            va1=ch[L][0][0],va2=ch[L][0][1],va3=ch[L][1][0],va4=ch[L][1][1];
            fn=(L+1)*big;
            for(int i=L*big;i<fn;i++){
                tmp1=va1*a[i]+va2*b[i] ;
                tmp2=va3*a[i]+va4*b[i] ;
                a[i]=tmp1;
                b[i]=tmp2;
            }
            flag[L]=0;
            ch[L][0][0]=1; ch[L][0][1]=0;ch[L][1][0]=0; ch[L][1][1]=1;
        }
        for(int i=x;i<=y;i++){
            a2[R]=a2[R]-a[i]*a[i] ;
            b2[R]=b2[R]-b[i]*b[i] ;
            ab[R]=ab[R]-a[i]*b[i] ;
            tmp1=p*a[i] +q*b[i] ;
            tmp2=r*a[i] +s*b[i] ;
            a[i]=tmp1;
            b[i]=tmp2;
            a2[R]=a2[R]+a[i]*a[i] ;
            b2[R]=b2[R]+b[i]*b[i] ;
            ab[R]=ab[R]+a[i]*b[i] ;
        }
        return;
    }
    if(flag[L]){
        fn=(L+1)*big;
        va1=ch[L][0][0],va2=ch[L][0][1],va3=ch[L][1][0],va4=ch[L][1][1];
        for(int i=L*big;i<fn;++i){
            tmp1=va1*a[i] +va2*b[i] ;
            tmp2=va3*a[i] +va4*b[i] ;
            a[i]=tmp1;
            b[i]=tmp2;
        }
        flag[L]=0;
        ch[L][0][0]=1; ch[L][0][1]=0; ch[L][1][0]=0; ch[L][1][1]=1;
    }
    fn = (L+1)*big;
    for(int i=x;i<fn;++i){
        a2[L]=a2[L]-a[i]*a[i] ;
        b2[L]=b2[L]-b[i]*b[i] ;
        ab[L]=ab[L]-a[i]*b[i] ;
        tmp1=p*a[i] +q*b[i] ;
        tmp2=r*a[i] +s*b[i] ;
        a[i]=tmp1;b[i]=tmp2;
        a2[L]=a2[L]+a[i]*a[i] ;
        b2[L]=b2[L]+b[i]*b[i] ;
        ab[L]=ab[L]+a[i]*b[i] ;
    }
    if(flag[R]){
        fn=(R+1)*big;
        va1=ch[R][0][0],va2=ch[R][0][1],va3=ch[R][1][0],va4=ch[R][1][1];
        for(int i=R*big;i<fn;i++){
            tmp1=va1*a[i] +va2*b[i] ;
            tmp2=va3*a[i] +va4*b[i] ;
            a[i]=tmp1; b[i]=tmp2;
        }
        ch[R][0][0]=1; ch[R][0][1]=0; ch[R][1][0]=0; ch[R][1][1]=1;
        flag[R]=0;
    }
    for(int i=R*big;i<=y;++i){
            tmp1=p*a[i] +q*b[i] ;
            tmp2=r*a[i] +s*b[i] ;
            a2[R]=a2[R]-a[i]*a[i] ;
            b2[R]=b2[R]-b[i]*b[i] ;
            ab[R]=ab[R]-a[i]*b[i] ;
            a[i]=tmp1;b[i]=tmp2;
            a2[R]=a2[R]+a[i]*a[i] ;
            b2[R]=b2[R]+b[i]*b[i] ;
            ab[R]=ab[R]+a[i]*b[i] ;
    }

    for(int i=L+1;i<R;++i){
        va1=p*ch[i][0][0]+q*ch[i][1][0] ;va2=p*ch[i][0][1]+q*ch[i][1][1] ;
        va3=r*ch[i][0][0]+s*ch[i][1][0] ;va4=r*ch[i][0][1]+s*ch[i][1][1] ;
        ch[i][0][0]=va1;ch[i][0][1]=va2;ch[i][1][0]=va3;ch[i][1][1]=va4;
        flag[i]=1;
        t1=p*r*a2[i]+q*s*b2[i]+(p*s+r*q)*ab[i] ;
        t2=p*p*a2[i]+q*q*b2[i]+2*p*q*ab[i];
        t3=r*r*a2[i]+s*s*b2[i]+2*s*r*ab[i] ;
        ab[i]=t1;a2[i]=t2;b2[i]=t3;
    }

    return;
}

void query(){
    L=x/big,R=y/big;
    if(R==L){
        ret=0;
        va1=ch[L][0][0],va2=ch[L][0][1],va3=ch[L][1][0],va4=ch[L][1][1];
        if(flag[L]){
        fn=(L+1)*big;
        for(int i=L*big;i<fn;i++){
            tmp1=va1*a[i]+va2*b[i];
            tmp2=va3*a[i]+va4*b[i];
            a[i]=tmp1; b[i]=tmp2;
        }
        flag[L]=0;
        ch[L][0][0]=1; ch[L][0][1]=0; ch[L][1][0]=0; ch[L][1][1]=1;
        }
        for(int i=x;i<=y;i++){
            ret=ret+a[i]*b[i] ;
        }
        printf("%u
",ret );
        return;
    }
    ret=0;
    if(flag[L]){
        va1=ch[L][0][0],va2=ch[L][0][1],va3=ch[L][1][0],va4=ch[L][1][1];
        fn = (L+1)*big;
        for(int i=L*big;i<fn;i++){
            tmp1=va1*a[i] +va2*b[i];
            tmp2=va3*a[i] +va4*b[i];
            a[i]=tmp1;b[i]=tmp2;
        }
        flag[L]=0;
        ch[L][0][0]=1; ch[L][0][1]=0; ch[L][1][0]=0; ch[L][1][1]=1;
    }
    fn = (L+1)*big;
    for(int i=x;i<fn;i++){
        ret=ret+a[i]*b[i];
    }
    if(flag[R]){
        va1=ch[R][0][0],va2=ch[R][0][1],va3=ch[R][1][0],va4=ch[R][1][1];
        fn = (R+1)*big;
        for(int i=R*big;i<fn;i++){
            tmp1=va1*a[i]+va2*b[i];
            tmp2=va3*a[i]+va4*b[i];
            a[i]=tmp1;
            b[i]=tmp2;
        }
        flag[R]=0;
        ch[R][0][0]=1; ch[R][0][1]=0; ch[R][1][0]=0; ch[R][1][1]=1;
    }
    for(int i=R*big;i<=y;i++){
        ret=ret+a[i]*b[i];
    }
    for(int i=L+1;i<R;i++){
        ret=ret+ab[i] ;
    }
    printf("%u
",ret);
    return;
}

int main(){
    scanf("%d%d",&n,&m);
    big=sqrt(n);
    for(int i=0;i<n;i++){
        scanf("%u",&a[i]);
    }
    for(int i=0;i<n;i++){
       scanf("%u",&b[i]);
    }
    init();
    for(int i=0;i<m;i++){
        scanf("%u",&ss);
        if(ss==1){
            scanf("%u%u%u%u%u%u",&x,&y,&p,&q,&r,&s);
            --x;--y;
            update();
        }
        else{
            scanf("%u%u",&x,&y);
            --x;--y;
            query();
        }
    }
    return 0;
}





原文地址:https://www.cnblogs.com/zhangxianlong/p/10672569.html