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

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

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

先阐述一下最 navie 的暴力。枚举每一个操作,自前向后,若遇到它的左端点,则代表接下来的都需要递推了,也就是 \(f_{l-1}=0,f_l=1,f_{l+1}=f_l+f_{l-1}\),如是递推下去,但是到 \(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;
} 

posted @ 2022-08-24 19:38  FxorG  阅读(40)  评论(0编辑  收藏  举报