魔法树

Description

人类和精灵的联络被巫妖王破坏了,巫妖王决定消灭精灵族以绝后患。 拉席克:“亡灵正在攻过来!” 法里奥:“看来只有暂时抵挡了。” 作为精灵的先知,法里奥召唤出了一排树木,挡住了亡灵的进攻,可是亡灵改变战略,集中攻击一段树木,法里奥为了加强防御不 得不施魔法将这一段树加高。 
对于亡灵的每一次进攻,法里奥需要知道进攻区间的防御力, 定义区间的防御力为这一段区间所有树的高度和。 
法里奥还在忙着施法,所以需要你来帮他完成这个任务

Input

第一行,两个数 N,M,表示树的数量和操作数,数的编号为0到N−1。 
第二行 N 个数,表示树的初始高度。 
接下来 M 行,每行一个操作: 
C l r h 表示法里奥施法将 l 到 r 的树加高了 ℎ 
Q l r 表示亡灵攻击了 l 到 r,法里奥向你询问 l 到 r 之间树的高度和。

Output

对于每一个 Q 操作,输出一个结果。

Sample Input

 

10 5
1 2 3 4 5 6 7 8 9 10
Q 3 3
Q 0 9
Q 1 3
C 2 5 3
Q 1 3

 

Sample Output

 

4
55
9
15

 

Hint

N≤1000000,M≤5000 初始高度不超过 100


【分析】

        这道题的M其实很小,那么我们只需要记下每次操作,然后每次询问暴力扫一遍即可。

        但是我用这道题来演示一下堆式线段树(也叫完全二叉线段树)


【代码】

/*
    若当前这段的编号为id。
	则在堆式线段树中,其左儿子编号为id*2,右儿子编号为id*2+1
	(跟堆的记法一样)
	这样可以压常数,有些时候很有用。 
*/ 
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<ctime>
#include<iostream>
#include<algorithm>
using namespace std;
struct node{                   
	int L,R;
	long long sum,lazy;
}Tree[4000005];
int N,M,h[1000005];;
char t[100];
void _in(int &x)
{
	char t=getchar();
	while(t<'0'||'9'<t) t=getchar();
	for(x=t-'0',t=getchar();'0'<=t&&t<='9';x=x*10+t-'0',t=getchar()); 
}
void _out(long long x,int j=1)
{
    if(x==0)printf("0");
    for(;x;x/=10,j++) t[j]=x%10+'0';
    for(j--;j;j--)putchar(t[j]);
    putchar('
');
}
void _putdown(int id)
{
	Tree[(id<<1)].lazy+=Tree[id].lazy;
	Tree[(id<<1)+1].lazy+=Tree[id].lazy;
	Tree[(id<<1)].sum+=Tree[id].lazy*((long long)(Tree[(id<<1)].R+1-Tree[(id<<1)].L));
	Tree[(id<<1)+1].sum+=Tree[id].lazy*((long long)(Tree[(id<<1)+1].R+1-Tree[(id<<1)+1].L));
	Tree[id].lazy=0;
}
void _built(int id,int l,int r)
{
	Tree[id].L=l;Tree[id].R=r;
	if(l==r)
	{
	    Tree[id].sum=h[l];
	    return;
	}
	int mid=(l+r)>>1;
	_built((id<<1),l,mid);
	_built((id<<1)+1,mid+1,r);
	Tree[id].sum=Tree[(id<<1)].sum+Tree[(id<<1)+1].sum;
}
void _insert(int id,int l,int r,int v)
{
	if(Tree[id].lazy!=0&&Tree[id].R!=Tree[id].L)
	    _putdown(id);
	if(l<=Tree[id].L&&Tree[id].R<=r)
	{
		Tree[id].lazy+=v;
		Tree[id].sum+=((long long)(v))*((long long)(Tree[id].R+1-Tree[id].L));
		return;
	}
	if(!(r<Tree[(id<<1)].L||Tree[(id<<1)].R<l)) _insert((id<<1),l,r,v);
	if(!(r<Tree[(id<<1)+1].L||Tree[(id<<1)+1].R<l)) _insert((id<<1)+1,l,r,v);
	Tree[id].sum=Tree[(id<<1)].sum+Tree[(id<<1)+1].sum;
}
long long _findans(int id,int l,int r)
{
	if(Tree[id].lazy!=0&&Tree[id].L!=Tree[id].R)
	    _putdown(id);
	if(l<=Tree[id].L&&Tree[id].R<=r)
	    return Tree[id].sum;
	long long temp=0;
	if(!(r<Tree[(id<<1)].L||Tree[(id<<1)].R<l))
	    temp+=_findans((id<<1),l,r);
	if(!(r<Tree[(id<<1)+1].L||Tree[(id<<1)+1].R<l))
	    temp+=_findans((id<<1)+1,l,r);
	return temp;
}
void _init()
{
	_in(N);_in(M);
	for(int i=1;i<=N;i++)
	    _in(h[i]);
	_built(1,1,N);
}
void _solve()
{
	string s;
	int x,y,z;
	for(int i=1;i<=M;i++)
	{
		cin>>s;
		_in(x);_in(y);
		x++;y++;
		if(s[0]=='C')
		{
			_in(z);
			_insert(1,x,y,z);
		}
		else
		    _out(_findans(1,x,y));
	}
}
int main()
{
	_init();
	_solve();
	return 0;
}



原文地址:https://www.cnblogs.com/riskyer/p/3366064.html