博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【洛谷5309】[Ynoi2012] D1T1(分块)
阅读量:4668 次
发布时间:2019-06-09

本文共 2965 字,大约阅读时间需要 9 分钟。

大致题意: 两种操作,区间求和,将形如\(ax+y\)的位置的元素值加\(z\)

分块

这种题目显然就是按照\(x\)\(\sqrt n\)的大小关系来分块。

对于\(x>\sqrt n\),我们用分块来实现单点修改,区间求和

对于\(x\le\sqrt n\),我们考虑枚举\(x\),则可发现每次询问都由若干长度为\(x\)的完整的段和最后一小段不完整的段组成。

那么我们可以对于\(x\),维护一个前缀和数组,然后每次就相当于求出整段和的若干倍加上其中一部分的值(这可以用前缀和差分求出)。

这有点难描述,而且我语文不好,因此直接看代码吧(代码有注释)。

\(P.S.\)\(hl666\)大佬说,似乎这里不用\(\sqrt n\)作为临界值而用常量\(40\)更优?

代码

#include
#define Tp template
#define Ts template
#define Reg register#define RI Reg int#define Con const#define CI Con int&#define I inline#define W while#define N 200000#define SN 30#define X 1000000007#define min(x,y) ((x)<(y)?(x):(y))#define Inc(x,y) ((x+=(y))>=X&&(x-=X))#define XSum(x,y) ((x)+(y)>=X?(x)+(y)-X:(x)+(y))#define XSub(x,y) ((x)<(y)?(x)-(y)+X:(x)-(y))using namespace std;int n,a[N+5];class FastIO{ private: #define FS 100000 #define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++) #define pc(c) (C^FS?FO[C++]=c:(fwrite(FO,1,C,stdout),FO[(C=0)++]=c)) #define tn (x<<3)+(x<<1) #define D isdigit(c=tc()) int T,C;char c,*A,*B,FI[FS],FO[FS],S[FS]; public: I FastIO() {A=B=FI;} Tp I void read(Ty& x) {x=0;W(!D);W(x=tn+(c&15),D);} Tp I void write(Ty x) {W(S[++T]=x%10+48,x/=10);W(T) pc(S[T--]);} Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);} Tp I void writeln(Con Ty& x) {write(x),pc('\n');} I void clear() {fwrite(FO,1,C,stdout),C=0;}}F;class LargeBlock//对于大的情况{ private: #define SZ 450 #define P(x) (((x)-1)/Bs+1) int Bs,p[N+5],a[N+5],s[SZ+5]; public: I void Init(CI x,int* v) {Bs=sqrt(x);for(RI i=1;i<=n;++i) Inc(s[p[i]=P(i)],a[i]=v[i]);}//初始化 I void U(CI x,CI y,CI v) {for(RI i=y;i<=n;i+=x) Inc(a[i],v),Inc(s[p[i]],v);}//修改,相当于若干单点修改 I int Q(CI l,CI r)//区间求和 { RI i,t=0;if(p[l]==p[r]) {for(i=l;i<=r;++i) Inc(t,a[i]);return t;} for(i=p[l]*Bs;i>=l;--i) Inc(t,a[i]);for(i=(p[r]-1)*Bs+1;i<=r;++i) Inc(t,a[i]); for(i=p[l]+1;i^p[r];++i) Inc(t,s[i]);return t; }}B;class SmallBlock//对于小的情况{ private: int n,a[SN+5]; public: I void Init(CI x) {n=x;} I void U(CI y,CI v) {for(RI i=y%n;i^n;++i) Inc(a[i],v);}//暴力维护前缀和 I int Q(CI x,CI y) { RI t=1LL*(y-x+1)/n*a[n-1]%X,tx=x%n,ty=y%n;//先求出若干完整块的值 if(x+(y-x+1)/n*n>y) return t;//若不存在不完整块直接返回 tx<=ty?Inc(t,XSub(a[ty],tx?a[tx-1]:0))://如果连成一段 Inc(t,XSum(XSub(a[n-1],tx?a[tx-1]:0),a[ty]));//如果一半在尾,一半在头 return t; }}S[SN+5];int main(){ RI Qt,i,op,x,y,z,ans;for(F.read(n,Qt),i=1;i<=n;++i) F.read(a[i]);//读入 for(B.Init(n,a),i=1;i<=SN;++i) S[i].Init(i);W(Qt--) { if(F.read(op,x,y),op^2) {F.read(z),x<=SN?S[x].U(y,z):B.U(x,y,z);continue;}//处理修改 for(ans=B.Q(x,y),i=1;i<=SN;++i) Inc(ans,S[i].Q(x,y));F.writeln(ans);//处理询问 }return F.clear(),0;}

转载于:https://www.cnblogs.com/chenxiaoran666/p/Luogu5309.html

你可能感兴趣的文章
浅析Hibernate映射(五)——集合映射
查看>>
java.lang.ClassNotFoundException: com.sun.xml.ws.spi.ProviderImpl解决办法
查看>>
检测到在集成的托管管道模式下不适用的ASP.NET设置的解决方法(非简单设置为【经典】模式)。 - CatcherX...
查看>>
Bitmap处理
查看>>
C语言记录汇总
查看>>
webservices系列(三)——调用线上webservice(天气预报和号码查询)
查看>>
callback 模式
查看>>
什么是servlet
查看>>
Something about TFS
查看>>
用haslib给字符加密
查看>>
mysql limit分页查询效率
查看>>
adb shell 命令之----pm
查看>>
Git常用命令
查看>>
c#利用zlib.net对文件进行deflate流压缩(和java程序压缩生成一样)
查看>>
SQL Server中Text和varchar(max)数据类型区别
查看>>
Markdown的基本语法
查看>>
lintcode-87-删除二叉查找树的节点
查看>>
Creating a blocking Queue<T> in .NET
查看>>
621. Task Scheduler
查看>>
IIS支持flv文件
查看>>