牛客 28(B.数据结构 线段树)

https://ac.nowcoder.com/acm/contest/200/B

题解:线段树,注意,我一开始的时候写错了,一开始build的时候lazy数组的初始化搞错了,后来又发现在每一次pushdown的时候都要进行乘法和加法两个lazy的判别(之前我是分flag,只对一种判别)。

#include<bits/stdc++.h>
#define MID (l+r)>>1
#define lson step<<1
#define rson step<<1|1
#define LL long long
using namespace std;
const int maxn=10005;
int n,m;
LL a[maxn],pf[maxn<<2],sum[maxn<<2];
int lazy1[maxn<<2],lazy2[maxn<<2];
void pushup(int step)
{
	sum[step]=sum[lson]+sum[rson];
	pf[step]=pf[lson]+pf[rson];
}
void pushdown(int l,int r,int flag,int step)
{
	int mid=MID;
	if(lazy2[step]!=1)
	{
		lazy2[lson]*=lazy2[step];lazy2[rson]*=lazy2[step];
		
		pf[lson]*=lazy2[step]*lazy2[step];
		pf[rson]*=lazy2[step]*lazy2[step];
		
		sum[lson]*=lazy2[step];
		sum[rson]*=lazy2[step];
		lazy2[step]=1;
	}
	if(lazy1[step])
	{
		lazy1[lson]+=lazy1[step];lazy1[rson]+=lazy1[step];
		
		pf[lson]+=lazy1[step]*lazy1[step]*(mid-l+1)+2*lazy1[step]*sum[lson];
		pf[rson]+=lazy1[step]*lazy1[step]*(r-mid)+2*lazy1[step]*sum[rson];
		
		sum[lson]+=(mid-l+1)*lazy1[step];	
		sum[rson]+=(r-mid)*lazy1[step];
		
		lazy1[step]=0;
	}		
}
void build(int l,int r,int step)
{
	lazy1[step]=0;
	lazy2[step]=1;
	if(l==r)
	{
		sum[step]=a[l];
		pf[step]=a[l]*a[l];
		return ;	
	}	
	int mid=MID;
	build(l,mid,lson);
	build(mid+1,r,rson);
	pushup(step);
} 
void update(int l,int r,int left,int right,int flag,int x,int step)
{
	if(left<=l&&right>=r)
	{
		if(flag==4)
		{
			lazy1[step]+=x;
			pf[step]+=x*x*(r-l+1)+2*x*sum[step];
			sum[step]+=(r-l+1)*x;
		}
		else
		{
			lazy2[step]*=x;
			sum[step]*=x;
			pf[step]*=x*x;
		}
		return ;
	}
	int mid=MID;
	pushdown(l,r,flag,step);
	if(left<=mid)
	{
		update(l,mid,left,right,flag,x,lson);
	}
	if(right>mid)
	{
		update(mid+1,r,left,right,flag,x,rson);
	}
	pushup(step); 
}
LL query(int l,int r,int left,int right,int flag,int step)
{
	if(l==left&&r==right)
	{
		if(flag==1)	return sum[step];
		if(flag==2) return pf[step];
	}
	int mid=MID;
	pushdown(l,r,flag,step);
	LL res=0;
	if(right<=mid)
		res+=query(l,mid,left,right,flag,lson);
	else if(left>mid)
		res+=query(mid+1,r,left,right,flag,rson);
	else
	{
		res+=query(l,mid,left,mid,flag,lson);
		res+=query(mid+1,r,mid+1,right,flag,rson);
	}
	return res;
}
int main()
{
	ios::sync_with_stdio(false);
	cin>>n>>m;
	for(int i=1;i<=n;i++)
		cin>>a[i];
	build(1,n,1);
	LL ans;
	for(int i=1;i<=m;i++)
	{
		int k,x,l,r;
		cin>>k;
		if(k==1||k==2)
		{
			cin>>l>>r;
			ans=query(1,n,l,r,k,1);
			cout << ans << endl;
		}
		else
		{
			cin>>l>>r>>x;
			update(1,n,l,r,k,x,1);
		}
	}
	return 0;
 } 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值