codevs 1082 线段树练习3

#include
#include
#include
using namespace std;
int n,q;
long long sum,a[200001];
struct tr
{
	int l,r;
	long long v,ad;
}s[2000001];
void build(int i,int l,int r)
{
	s[i].l=l;s[i].r=r;
	if(l==r)
	{
		s[i].v=a[l];return;
	}
	build(i*2,l,(l+r)/2);
	build(i*2+1,(l+r)/2+1,r);
	s[i].v=s[i*2].v+s[i*2+1].v;
}
void ask(int i,int ll,int rr)
{
	if(s[i].ad!=0)
	{
		s[i].v+=s[i].ad*(s[i].r-s[i].l+1);
		s[2*i].ad+=s[i].ad;
		s[2*i+1].ad+=s[i].ad;
		s[i].ad=0;
	}
	if(s[i].l>=ll&&s[i].r<=rr)
	{
		sum+=s[i].v;
		return;
	}
	int kk=i*2;
	if(s[kk].r>=ll)ask(kk,ll,rr);
	if(s[kk+1].l<=rr)ask(kk+1,ll,rr);
}
void add(int i,int ll,int rr,int x)
{
	if(s[i].l>=ll&&s[i].r<=rr)
	{
		s[i].ad+=x;
		return;
	}
	if(ll>=s[i].l&&rr<=s[i].r)s[i].v+=x*(rr-ll+1);
	else s[i].v+=x*(min(abs(s[i].r-ll+1),abs(rr-s[i].l+1)));
	if(s[i].ad!=0)
	{
		s[i].v+=(s[i].r-s[i].l+1)*s[i].ad;
		s[2*i].ad+=s[i].ad;
		s[2*i+1].ad+=s[i].ad;
		s[i].ad=0;
	}
	int kk=i*2;
	if(s[kk].r>=ll)add(kk,ll,rr,x);
	if(s[kk+1].l<=rr)add(kk+1,ll,rr,x);
}
int main ()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	cin>>a[i];
	cin>>q;
	build(1,1,n);
	for(int i=1;i<=q;i++)
	{
		int k;cin>>k;
		if(k==1)
		{
			int b,c,d;
			cin>>b>>c>>d;
			add(1,b,c,d);
		}
		if(k==2)
		{
			int b,c;
			cin>>b>>c;
			sum=0;
			ask(1,b,c);
			cout< 
 

你可能感兴趣的:(此代码美丽)