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; }
相关文章推荐
- Mysql-proxy 读写分离中间组件
- hdu 1598 find the most comfortable road 枚举+并查集
- 练习打字第九天!
- 安卓3个练习题
- Find the Duplicate Number
- [iOS]从URL远程请求图片
- linux:error while loading shared libraries xx.so
- 进度条
- 《宗庆后:万有引力原理》:娃哈哈官方口径,可以作为了解娃哈哈及其相关领域的重要参考资料。三星推荐
- 微信课堂的初步确立
- 第十一周项目4—教师兼干部类
- SpringMVC源代码学习(三)DispatcherServlet
- MySql获取数据库大小
- 1. Two Sum
- python urllib 和urllib2的区别
- LintCode 加油站
- Android studio -SVN 的使用
- 团队冲刺第一天
- 解决Windows挂起状态
- fragment和activity通信问题