您的位置:首页 > 其它

CCNU 校赛J---分桶法

2016-05-13 21:48 375 查看




题意如上,标程是线段树,每个节点维护  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\n",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\n",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;
}



                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: