3468

/*
还是老老实实的先用线段树来解决吧

区间和,区间更新

对于区间更新,这个如果更新到底的话,比较耗时,所以我新增了递增量。这样如果区间刚好和更新区域一样的话,就不要往下去了。只保存递增量

但是区间和的时候,就要有点变换了。出了拿出区间的和(已保存),还要计算从父节点过来的递增量。这个递增量和孩子节点的递增量是可以相加的

这样,区间和的复杂度没有增加,区间更新的复杂度小了点。

这样的时间大概是 1500ms
*/

// include file
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cctype>
#include <ctime>

#include <iostream>
#include <sstream>
#include <fstream>
#include <iomanip>
#include <bitset>

#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <set>
#include <list>
#include <functional>

using namespace std;

// typedef
typedef __int64 LL;

// 
#define read freopen("in.txt","r",stdin)
#define write freopen("out.txt","w",stdout)

#define Z(a) (a<<1)
#define Y(a) (a>>1)

const double eps = 1e-6;
const double INFf = 1e100;
const int INFi = 1000000000;
const LL INFll = (LL)1<<62;
const double Pi = acos(-1.0);

template<class T> inline T sqr(T a){return a*a;}
template<class T> inline T TMAX(T x,T y)
{
	if(x>y) return x;
	return y;
}
template<class T> inline T TMIN(T x,T y)
{
	if(x<y) return x;
	return y;
}
template<class T> inline T MMAX(T x,T y,T z)
{
	return TMAX(TMAX(x,y),z);
}
template<class T> inline T MMIN(T x,T y,T z)
{
	return TMIN(TMIN(x,y),z);
}
template<class T> inline void SWAP(T &x,T &y)
{
	T t = x;
	x = y;
	y = t;
}


// code begin
int N,M;
LL data[100010];

struct seg_tree_node
{
	LL left,right; //左右儿子
	LL sum; //和
	LL dz;
};

seg_tree_node mem[250000];

LL buildSegtree(LL l,LL r,int dx=1)
{
	mem[dx].left = l;
	mem[dx].right = r;
	mem[dx].dz = 0;
	if(l==r)
	{
		return mem[dx].sum = data[l];
	}
	
	LL z = buildSegtree(l,Y(l+r),Z(dx));
	LL y = buildSegtree(Y(l+r)+1,r,Z(dx)+1);
	return mem[dx].sum = (z+y);
}

void update(LL l,LL r,LL c,int dx=1)
{
	if( mem[dx].left==l && mem[dx].right == r)
	{
		mem[dx].dz += c;
		return ;
	}
	if(mem[dx].left==mem[dx].right)
	{//到达根节点
		mem[dx].sum += c;
		return;
	}
	mem[dx].sum += (r-l+1)*c;
	int zson = Z(dx),yson = Z(dx)+1;
	
	if( l>mem[zson].right )
	{//右儿子
		update(l,r,c,yson);	
	}
	else if( r<mem[yson].left )
	{//左儿子
		update(l,r,c,zson);
	}
	else
	{
		update(l,mem[zson].right,c,zson);
		update(mem[yson].left,r,c,yson);
	}
}

LL query(LL l,LL r,int dx=1,LL dz = 0)
{
	if(mem[dx].left==l && mem[dx].right==r)
	{
		return mem[dx].sum + (mem[dx].dz+dz)*(r-l+1);
	}
	int zson = Z(dx),yson = Z(dx)+1;
	if( l>mem[zson].right )
	{//右
		//printf("right\n");
		return query(l,r,yson,dz+mem[dx].dz);
	}
	else if( r<mem[yson].left )
	{//左
		//printf("left\n");
		return query(l,r,zson,dz+mem[dx].dz);
	}
	else
	{//分
		//printf("lr\n");
		return query(l,mem[zson].right,zson,dz+mem[dx].dz) + query(mem[yson].left,r,yson,dz+mem[dx].dz);
	}
}

int main()
{
	read;
	write;
	char cmd[3];
	LL a,b,c;
	while(scanf("%d %d",&N,&M)==2)
	{
		for(int i=1;i<=N;i++)
		{
			scanf("%I64d",data+i);
		}
		buildSegtree(1,N);
		while(M--)
		{
			scanf("%s",cmd);
			switch(cmd[0])
			{
			case 'C':
				//
				scanf("%I64d %I64d %I64d",&a,&b,&c);
				update(a,b,c);
				break;
			case 'Q':
				// 查询
				scanf("%I64d %I64d",&a,&b);
				printf("%I64d\n",query(a,b) );
				break;
			default:
				break;
			}
		}
	}
	return 0;
}
posted @ 2011-04-14 21:11  AC2012  阅读(231)  评论(0编辑  收藏  举报