Code Vs 1082 线段树练习 3

线段树写法
  
/*
作者:Greetrix
题目:p1082 线段树练习 3
*/


#include<iostream>
#include<cstdlib>
using namespace std;
const int M=200000;
struct Seb_tree
{
	int l;
	int r;
	long long sum;
	int col;
};
Seb_tree t[M*6+1];
int s[M*2];
int n, m;
void push_down(int k)
{
	if (t[k].col)
	{
		int lson=k*2;
		int rson=lson+1;
		t[lson].sum+=(t[lson].r-t[lson].l+1)*t[k].col;
		t[lson].col+=t[k].col;
		t[rson].sum+=(t[rson].r-t[rson].l+1)*t[k].col;
		t[rson].col+=t[k].col;
		t[k].col=0;
		
	}
}
long long  query(int l,int r , int k)
{
	if (t[k].l>=l && t[k].r<=r) return t[k].sum;
	int mid=(t[k].l+t[k].r)/2;
	push_down(k);
	if (r<=mid) query(l ,r, k*2);
	else if (l>mid) query(l ,r, k*2+1);
	else return query(l ,mid, k*2)+query(mid+1, r, k*2+1);
	
}
void updata(int l, int r, int col, int k)
{
	if (t[k].l>=l && t[k].r<=r)
	{
		t[k].sum+=(t[k].r-t[k].l+1)*col;
		t[k].col+=col;
		return;
	}
	push_down(k);
	int mid=(t[k].l+t[k].r)/2;
	if (r<=mid) updata(l ,r, col, k*2);
	else if (l>mid) updata(l, r, col, k*2+1);
	else 
	{
		updata(l ,mid,col,  k*2);
		updata(mid+1, r, col, k*2+1);
	}
	t[k].sum=t[k*2].sum+t[k*2+1].sum;
}
void build(int l, int r, int k)
{
	t[k].l=l;
	t[k].r=r;
	t[k].col=0;
	if (l==r) t[k].sum=s[r];
	else 
	{
		int mid=(l+r)/2;
		build(l ,mid, k*2);
		build(mid+1, r, k*2+1);
		t[k].sum=t[k*2].sum+t[k*2+1].sum;
	}
}
void debug()
{
	for (int i=1; i<=n*2+1; i++) cout<<t[i].sum<<" ";
	cout<<endl;
}
int main()
{
	cin>>n;
	for (int i=1; i<=n; i++) cin>>s[i];
	build(1, n, 1);
	//debug();
	cin>>m;
	while (m--)
	{
		int a, b, c, d;
		cin>>a;
		if (a==1)
		{
			cin>>b>>c>>d;
			updata(b, c, d, 1);
		}
		else 
		{
			cin>>b>>c;
			cout<<query(b,c,1)<<endl;	
		}
	}
	return 0;
}

树状数组写法:

  
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>

#define For1(x,n) for(int i=x; i<=n; i++)
using namespace std;
const int M=800010;
int a[M];
int d[M];
long long  d2[M];
long long  c[M];
int n, m;
int low_bit(int x) { return x & (x ^ (x-1));}
void debug()
{
	int sum=0;
	For1(1,n) {
		
	}
	printf("\n");
}
void updata1(int i, int val)
{
	while (i<=n)
	{
		d2[i]+=val;
		i+=low_bit(i);
	}
}
void updata(int i, int val)
{
	while (i<=n)
	{
		c[i]+=val;
		i+=low_bit(i);
	}
}
long long  query1(int i)
{
	long long  sum=0;
	while (i)
	{
		sum+=d2[i];
		i-=low_bit(i);
	}
	return sum;
}
long long   query(int i)
{
	long long  sum=0;
	while (i)
	{
		sum+=c[i];
		i-=low_bit(i);
	}
	return sum;
}
void init()
{
	memset(d, 0, sizeof(d));
	memset(c, 0, sizeof(c));
	memset(a,0,sizeof(a));
	memset(d2, 0, sizeof(d2));
	scanf("%d", &n);
	For1(1,n) scanf("%d ",&a[i]);
	a[0]=0;
	For1(1,n) 
	{
		updata(i,a[i]-a[i-1]);
		updata1(i,(a[i]-a[i-1])*i);
	}
}
void solve()
{
	scanf("%d",&m);
	For1(1,m)
	{
		int q, l, r, val;
		scanf("%d", &q);
		if (q==1)
		{
			scanf("%d %d %d", &l, &r, &val);
			updata(l,val);
			updata(r+1,-val);
			updata1(l,val*l);
			updata1(r+1, -val*(r+1));
		}
		else if (q==2)
		{
			long long   sum=0;
			scanf("%d %d", &l, &r);
			sum=(r+1)*query(r)-query1(r);
		    sum-=l*query(l-1)-query1(l-1);
		    printf("%lld\n", sum);
		}
	}
}
int main()
{
	init();
	solve();
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值