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


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

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

    先阐述一下最 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;
    } 
    
    
  • 相关阅读:
    Git理解
    Java基础之四、字符和字符串 异常处理
    魔方第三层复原技巧
    Java基础之三、类的特性和接口
    Java基础之二、类的知识
    Java基础之一、入门知识
    UML之三、建模元素(2)
    看懂棒球-规则、数据
    【转载】自助终端设备安全剖析 (深度好文)
    CVE-2017-12615 Tomcat远程代码执行
  • 原文地址:https://www.cnblogs.com/xugangfan/p/16621357.html
Copyright © 2020-2023  润新知