ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【模板】维护序列2(线段树)

2019-09-20 19:42:52  阅读:199  来源: 互联网

标签:rr 线段 mid ret summ 序列 LL 模板 MOD


内网传送门

【题目分析】

取模取挂可真是令人质壁分离。。。。

两两乘积和可以直接用两个区间的区间和相乘再加上两个区间各自的乘积和得到,而相邻乘积和直接两段相加再加上左区间右端点与右区间左端点乘积就好了。

注意+MOD%MOD

【代码~】

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL MAXN=1e5+10;
const LL MOD=1000000007;

LL n,q;
LL a[MAXN];
struct Tree{
	LL l,r;
	LL ll,rr;
	LL mul,sum,summ;
	void init(){l=r=ll=rr=sum=summ=mul=0;}
	friend inline Tree operator+(const Tree &a,const Tree &b){
		Tree ret;
		if(a.ll==a.rr&&!a.ll){
			ret=b;
			return ret;
		}
		ret.l=a.l,ret.r=a.r;
		ret.ll=a.ll,ret.rr=b.rr;
		ret.mul=((((a.summ*b.summ)%MOD+a.mul)%MOD+b.mul)%MOD+MOD)%MOD;
		ret.sum=(((a.sum+b.sum)%MOD+a.rr*b.ll%MOD)%MOD+MOD)%MOD;
		ret.summ=((a.summ+b.summ)%MOD+MOD)%MOD;
		return ret;
	}
}tr[MAXN<<2],ans;

LL Read(){
	LL i=0,f=1;
	char c=getchar();
	for(;(c>'9'||c<'0')&&c!='-';c=getchar());
	if(c=='-')  f=-1,c=getchar();
	for(;c>='0'&&c<='9';c=getchar())  i=(i<<3)+(i<<1)+c-'0';
	return i*f;
}

#define lc (root<<1)
#define rc (root<<1|1)
void push_up(LL root){tr[root]=tr[lc]+tr[rc];}

void build(LL root,LL l,LL r){
	tr[root].l=l,tr[root].r=r;	
	if(l==r){
		tr[root].ll=tr[root].rr=tr[root].summ=a[l];
		return ;
	}
	LL mid=(l+r)>>1;
	build(lc,l,mid);
	build(rc,mid+1,r);
	push_up(root);
}

void update(LL root,LL l,LL r,LL x,LL key){
	if(l==r){
		tr[root].ll=tr[root].rr=tr[root].summ=key;
		return ;
	}
	LL mid=(l+r)>>1;
	if(x<=mid)  update(lc,l,mid,x,key);
	else  update(rc,mid+1,r,x,key);
	push_up(root);
}

void query(LL root,LL l,LL r,LL L,LL R){
	if(l>R||r<L)  return ;
	if(L<=l&&r<=R){
		ans=ans+tr[root];
		return ;
	}
	LL mid=(l+r)>>1;
	if(R<=mid)  query(lc,l,mid,L,R);
	else{
		if(L>mid)  query(rc,mid+1,r,L,R);
		else  query(lc,l,mid,L,mid),query(rc,mid+1,r,mid+1,R);
	}
}

int main(){
	n=Read(),q=Read();
	for(LL i=1;i<=n;++i)  a[i]=Read();
	build(1,1,n);

	while(q--){
		char cz[5];
		scanf("%s",cz);
		LL l=Read(),r=Read();
		if(cz[0]=='M')  update(1,1,n,l,r);
		else{
			ans.init();
			query(1,1,n,l,r);
			if(cz[0]=='A')  cout<<ans.sum<<'\n';
			else  cout<<ans.mul<<'\n';
		}
	}
}

 

标签:rr,线段,mid,ret,summ,序列,LL,模板,MOD
来源: https://blog.csdn.net/g21glf/article/details/101073911

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有