相同形式的多组递推式的根号求法

拿斐波那契数列来说吧,区间加上一段。

显然对于单点求值得时候我们可以自前向后遍历,类扫描线一样。

先阐述一下最 navie 的暴力。枚举每一个操作,自前向后,若遇到它的左端点,则代表接下来的都需要递推了,也就是 fl1=0,fl=1,fl+1=fl+fl1,如是递推下去,但是到 r 结束了,下一位是 r+1 的时候,这个操作的贡献就要消掉了,也就是对应减去最后所得到的斐波那契数。

考虑合并所有操作变成一次遍历,最想当然正确的办法是不是扩域?但显然我们发现并不需要管那么多,因为加法满足结合律,自然这样搞下去即可。

然后套个根号分治!

http://www.51nod.com/Contest/ProblemSubmitDetail.html#judgeId=232860

#include <bits/stdc++.h> #define int long long #define pb push_back using namespace std; const int mod=19260817,N=(int)(1e5+5),M=350; int id[N],L[M],R[M],n,m,D,bl,a[N],sf[N],sum[N],p[N],sp[N],f[N],sd[N]; namespace sol1 { int tag1[M],tag2[M],tag3[M],s[N],ss[M]; void upt(int l,int r,int k,int d) { if(id[l]==id[r]) { for(int i=l;i<=r;i++) { s[i]=(s[i]+k+(i-l)*d%mod)%mod; ss[id[i]]=(ss[id[i]]+k+(i-l)*d%mod)%mod; } } else { for(int i=l;i<=R[id[l]];i++) s[i]=(s[i]+k+(i-l)*d%mod)%mod,ss[id[i]]=(ss[id[i]]+k+(i-l)*d%mod)%mod; for(int i=L[id[r]];i<=r;i++) s[i]=(s[i]+k+(i-l)*d%mod)%mod,ss[id[i]]=(ss[id[i]]+k+(i-l)*d%mod)%mod; for(int i=id[l]+1;i<id[r];i++) { tag1[i]=(tag1[i]+k)%mod; tag2[i]=(tag2[i]+(L[i]-l)*d%mod)%mod; tag3[i]=(tag3[i]+d)%mod; } } } int qry(int l,int r) { if(id[l]==id[r]) { int res=0; for(int i=l;i<=r;i++) res=((res+s[i])%mod+tag1[id[i]]+tag2[id[i]]+(i-L[id[i]])*tag3[id[i]]%mod)%mod; return res; } else { int res=0; for(int i=l;i<=R[id[l]];i++) res=((res+s[i])%mod+tag1[id[i]]+tag2[id[i]]+(i-L[id[i]])*tag3[id[i]]%mod)%mod; for(int i=L[id[r]];i<=r;i++) res=((res+s[i])%mod+tag1[id[i]]+tag2[id[i]]+(i-L[id[i]])*tag3[id[i]]%mod)%mod; for(int i=id[l]+1;i<id[r];i++) { int qwq=R[i]-L[i]+1; res=(res+qwq*tag1[i]%mod+tag2[i]*qwq%mod+sd[qwq-1]*tag3[i]%mod+ss[i])%mod; } return res; } } } namespace sol2 { int tag[M],s[N],ss[M]; void upt(int l,int r,int k) { if(id[l]==id[r]) { for(int i=l;i<=r;i++) { s[i]=(s[i]+k*p[i-l]%mod)%mod; ss[id[i]]=(ss[id[i]]+k*p[i-l]%mod)%mod; } } else { for(int i=l;i<=R[id[l]];i++) s[i]=(s[i]+k*p[i-l]%mod)%mod,ss[id[i]]=(ss[id[i]]+k*p[i-l]%mod)%mod; for(int i=L[id[r]];i<=r;i++) s[i]=(s[i]+k*p[i-l]%mod)%mod,ss[id[i]]=(ss[id[i]]+k*p[i-l]%mod)%mod; for(int i=id[l]+1;i<id[r];i++) { tag[i]=(tag[i]+k*p[L[i]-l]%mod)%mod; } } } int qry(int l,int r) { if(id[l]==id[r]) { int res=0; for(int i=l;i<=r;i++) res=((res+s[i])%mod+tag[id[i]]*p[i-L[id[i]]]%mod)%mod; return res; } else { int res=0; for(int i=l;i<=R[id[l]];i++) res=(res+s[i]+tag[id[i]]*p[i-L[id[i]]])%mod; for(int i=L[id[r]];i<=r;i++) res=(res+s[i]+tag[id[i]]*p[i-L[id[i]]])%mod; for(int i=id[l]+1;i<id[r];i++) res=(res+ss[i]+tag[i]*sp[R[i]-L[i]]%mod)%mod; return res; } } } int lim; namespace sol3 { vector<int>vecl[N],vecr[N]; int tot,l[N],r[N],v[N],val[N]; inline void re() { for(int i=1;i<=tot;i++) { vecl[l[i]].pb(i); vecr[r[i]].pb(i); } int a=0,b=0; for(int i=1;i<=n;i++) { int c=(a+b)%mod; val[i]=(val[i]+c)%mod; a=b; b=c; for(auto x:vecl[i]) b=(b+1)%mod,val[i]=(val[i]+1)%mod; for(auto x:vecr[i]) { int L=l[x],R=r[x]; b=(b-f[R-L+1]); a=(a-f[R-L]); } v[i]=(v[i-1]+val[i])%mod; } for(int i=1;i<=tot;i++) vecl[l[i]].clear(),vecr[r[i]].clear(); tot=0; } inline void upt(int x,int y) { l[++tot]=x; r[tot]=y; if(tot==lim) re(); } inline int qry(int x,int y) { int res=v[y]-v[x-1]; for(int i=1;i<=tot;i++) { int L=max(x,l[i]),R=min(y,r[i]); if(L<=R) { res=(res+sf[R-l[i]+1]-sf[L-l[i]])%mod; } } return res; } } signed main() { cin.tie(0); ios::sync_with_stdio(false); cin>>n>>m>>D; bl=sqrt(n); lim=sqrt(m); for(int i=1;i<=n;i++) cin>>a[i]; for(int i=1;i<=n;i++) a[i]=(a[i]+a[i-1])%mod; // for(int i=1;i<) for(int i=1;i<=n;i++) id[i]=(i-1)/bl+1; for(int i=1;i<=id[n];i++) L[i]=(i-1)*bl+1,R[i]=i*bl; R[id[n]]=n; // cout<<id[n]<<'\n'; // for(int i=1;i<=id[n];i++) cout<<L[i]<<" asdf "<<R[i]<<'\n'; p[0]=1; for(int i=1;i<=n;i++) p[i]=p[i-1]*D%mod; sp[0]=1; for(int i=1;i<=n;i++) sp[i]=(p[i]+sp[i-1])%mod; f[1]=1; f[2]=1; for(int i=3;i<=n;i++) f[i]=(f[i-1]+f[i-2])%mod; for(int i=1;i<=n;i++) sf[i]=(sf[i-1]+f[i])%mod; sd[0]=0; for(int i=1;i<=n;i++) sd[i]=(sd[i-1]+i)%mod; while(m--) { int op; cin>>op; if(op==1) { int l,r,x,y; cin>>l>>r>>x>>y; sol1::upt(l,r,x,y); } else if(op==2) { int l,r,x; cin>>l>>r>>x; sol2::upt(l,r,x); } else if(op==3) { int l,r; cin>>l>>r; sol3::upt(l,r); } else { int l,r; cin>>l>>r; int res=(sol2::qry(l,r)+sol1::qry(l,r)+sol3::qry(l,r))%mod; res=(res+a[r]-a[l-1])%mod; cout<<(res%mod+mod)%mod<<'\n'; } } return 0; }

__EOF__

本文作者F x o r G
本文链接https://www.cnblogs.com/xugangfan/p/16621357.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   FxorG  阅读(50)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示