BJOI2018链上二次求和


此题实际就是序列上的问题(只是链的话不一定(u<v),判一下)

(ans=sum_{i=l}^rsum_{j=i}^ns_j-s_{j-i}=sum_{i=l}^r(sum_{j=i}^ns_j-sum_{j=0}^{n-i}s_j))

改成二维前缀和

(ans=sum^r_{i=l}ss_n-ss_{i-1}-ss_{n-i})

用线段树维护二维前缀和即可(肯定是一个二次函数,拆开算贡献即可)

时间复杂度(O(nlog_n))

法2:

询问变前缀相减v

枚举作左右端点时的区间个数,右端点-左端点,(s_i)为前缀和

(ans=s_i(min(i,v)-min(n-i,v)))

于是线段树维护(s_i,s_i*i)即可,好像也没有变简单一点┭┮﹏┭┮

#include<bits/stdc++.h>
using namespace std;
inline int read(){
	int x=0,f=1;char c=getchar();
	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
	return f==1?x:-x;
}
#define ll long long 
#define lc (p<<1)
#define rc (p<<1|1)
const int N=2e5+4,mod=1e9+7,inv2=5e8+4;
int n,m,a[N],la[N<<2],lb[N<<2],le[N<<2],t[N<<2],lza[N<<2],lzb[N<<2],lzc[N<<2];
void build(int p,int l,int r){
	le[p]=r-l+1;
	if(l==r){
		t[p]=a[l];
		la[p]=(ll)l*l%mod;
		lb[p]=l;
		return;
	}
	int mid=l+r>>1;
	build(lc,l,mid);
	build(rc,mid+1,r);
	t[p]=(t[lc]+t[rc])%mod;
	la[p]=(la[lc]+la[rc])%mod;
	lb[p]=(lb[lc]+lb[rc])%mod;
}
inline void pushnow(int p,int a,int b,int c){
	t[p]=((ll)a*la[p]%mod+(ll)b*lb[p]%mod+(ll)c*le[p]%mod+t[p])%mod;
	lza[p]=(lza[p]+a)%mod;lzb[p]=(lzb[p]+b)%mod;lzc[p]=(lzc[p]+c)%mod;
} 
inline void pushdown(int p){
	if(!lza[p]&&!lzb[p]&&!lzc[p])return;
	pushnow(lc,lza[p],lzb[p],lzc[p]);
	pushnow(rc,lza[p],lzb[p],lzc[p]);
	lza[p]=lzb[p]=lzc[p]=0;
}
void modify(int p,int l,int r,int ql,int qr,int va,int vb,int vc){
	if(ql<=l&&r<=qr){
		pushnow(p,va,vb,vc);
		return;
	}
	int mid=l+r>>1;
	pushdown(p);
	if(ql<=mid)modify(lc,l,mid,ql,qr,va,vb,vc);
	if(mid<qr)modify(rc,mid+1,r,ql,qr,va,vb,vc);
	t[p]=(t[lc]+t[rc])%mod;
}
int query(int p,int l,int r,int ql,int qr){
	if(ql<=l&&r<=qr)return t[p];
	int mid=l+r>>1,ret=0;
	pushdown(p);
	if(ql<=mid)ret=(ret+query(lc,l,mid,ql,qr))%mod;
	if(mid<qr)ret=(ret+query(rc,mid+1,r,ql,qr))%mod;
	return ret;
}
int main(){
	n=read();m=read();
	for(int i=1;i<=n;i++){
		a[i]=read();
		a[i]=(a[i]+a[i-1])%mod;
	}
	for(int i=1;i<=n;i++)a[i]=(a[i]+a[i-1])%mod;
	build(1,1,n);
	while(m--){
		static int op,l,r,x,len;
		op=read();l=read();r=read();
		if(l>r)l^=r^=l^=r;
		if(op==2){
			cout<<((ll)(r-l+1)*query(1,1,n,n,n)-(r>1?query(1,1,n,max(1,l-1),r-1):0)-(l<n?query(1,1,n,max(1,n-r),n-l):0)+(mod<<1))%mod<<"
"; 
		}
		else{
			x=read();len=r-l+1;
			modify(1,1,n,l,r,(ll)inv2*x%mod,((ll)(3-2*l)*inv2%mod*x%mod+mod)%mod,(((ll)l*l-3ll*l+2)%mod*inv2%mod*x%mod+mod)%mod);
			if(r<n)modify(1,1,n,r+1,n,0,(ll)len*x%mod,((ll)(len+1)*inv2-r+mod)%mod*len%mod*x%mod);
		}
	} 
	return (0-0);
}
原文地址:https://www.cnblogs.com/aurora2004/p/12579897.html