记录编号 142282 评测结果 AAAAAAAAAA
题目名称 数列操作C 最终得分 100
用户昵称 Gravatarwolf. 是否通过 通过
代码语言 C++ 运行时间 0.570 s
提交时间 2014-12-07 01:31:25 内存使用 0.31 MiB
显示代码纯文本
#include<iostream>
#include<fstream>
#include<bitset>
#include<vector>
#include<deque>
#include<map>
#include<string>
#include<algorithm>
#include<cmath>
#include<ctime>
#include<cstdio>
using namespace std;
#if defined wolf
ofstream nnew("shuliec.in",ios::app);
ifstream fin("shuliec.in");
#define fout cout
#else
ifstream fin("shuliec.in");
ofstream fout("shuliec.out");
#endif
/////////////////////////////////线段树
class leaf{
public:
	int left;
	int right;
	int up;
	long long add;
	long long n;
	leaf(){
		left=0;//该点区间[left,right]
		right=0;
		add=0;// ADD命令产生的值
		up=0;//  表示"该区间每个值都应加上该 up "用于向下求和时用  加快运行速度 根据需要利用区间大小计算
		n=0;//起始时该节点所控制范围的和  初始化后不修改该值
	}
};
vector<leaf> tree;//保存所有节点
vector<int> sign;//保存叶子节点在树中的下标,加快从叶子节点初始化的速度
void _build(int p,int l,int r){//构造线段树
	tree[p].left=l;//确立区间范围
	tree[p].right=r;
	if(l>=r){// true时为叶子
		sign[l]=p;//标记叶子节点的下标
		return;
	}
	_build(p*2,l,(l+r)/2);//递归创建树
	_build(p*2+1,(l+r)/2+1,r);//2*p与2*p+1为儿子
}
void _refresh_up(int p,int v){//由叶子节点向上更新
	tree[p].n+=v;
	if(p==1){//根
		return;
	}
	_refresh_up(p/2,v);//找爸爸
}
long long _sum(int p,int l,int r){
	if(tree[p].right==r&&tree[p].left==l){//该节点恰好为所修改的范围
		return tree[p].n+tree[p].add+(tree[p].right-tree[p].left+1)*tree[p].up;//将该区间原始的数、新的数、未加的数求和返回
	}
	int mid=(tree[p].left+tree[p].right)/2;
	tree[2*p].up+=tree[p].up;//将up拆给儿子
	tree[2*p+1].up+=tree[p].up;
	tree[p].add+=(tree[p].right-tree[p].left+1)*tree[p].up;//应将up转化为add储存
	tree[p].up=0;//删除分解过了的up
	if(r<=mid){//二分向下 不解释
		return _sum(2*p,l,r);//递归--->逐级返回
	}else if(l>mid){
		return _sum(2*p+1,l,r);
	}else{
		return _sum(2*p+1,mid+1,r)+_sum(2*p,l,mid);
	}
}
void _add(int p,int l,int r,int v){
	int mid=(tree[p].left+tree[p].right)/2;
	if(tree[p].right==r&&tree[p].left==l){//该节点恰好为所修改的范围
		tree[p].up+=v;//给该节点记录一下即可
		return;
	}
	tree[p].add+=(r-l+1)*v;//将up=v转化
	if(r<=mid){//二分向下
		_add(2*p,l,r,v);
	}else if(l>mid){
		_add(2*p+1,l,r,v);
	}else{
		_add(2*p,l,mid,v);
		_add(2*p+1,mid+1,r,v);
	}
}
///////////////////////////树状数组
vector<long long> TT[3];
int lowbit(int n){//基础不解释
	return n&(-n);
}
long long _ssum(int cmd,int p,int l,int r){//一个函数干三个活
	if(cmd==2){//最扯最抽象的部分
		long long sum=0,left=0,right=0;
		sum+=_ssum(0,r,0,0)-_ssum(0,l-1,0,0);
		
		right+=(r+1)*_ssum(1,r,0,0);
		for(int i=r;i>0;i-=lowbit(i)){
			right-=TT[2][i];
		}
		
		left+=l*_ssum(1,l-1,0,0);
		for(int i=l-1;i>0;i-=lowbit(i)){
			left-=TT[2][i];
		}
		
		return sum+(right-left);
	}
	if(cmd==1){//差分前N项和
		long long sum=0;
		for(int i=p;i>0;i-=lowbit(i)){
			sum+=TT[1][i];
		}
		return sum;
	}
	if(cmd==0){//原数列前N项和
		long long sum=0;
		for(int i=p;i>0;i-=lowbit(i)){
			sum+=TT[0][i];
		}
		return sum;
	}
}
void _aadd(bool cmd,int p,int l,int r,int n){//一个函数两项任务
	if(!cmd){//在原数列中添加一值
		for(int i=p;i<TT[0].size();i+=lowbit(i)){
			TT[0][i]+=n;
		}
		return;
	}
	if(cmd){//在差分数列中添加一个值
		for(int i=l;i<TT[0].size();i+=lowbit(i)){
			TT[1][i]+=n;
		}
		for(int i=r+1;i<TT[0].size();i+=lowbit(i)){
			TT[1][i]-=n;
		}
		int e;
		e=n*l;
		for(int i=l;i<TT[0].size();i+=lowbit(i)){
			TT[2][i]+=e;
		}
		e=n*(r+1);
		for(int i=r+1;i<TT[0].size();i+=lowbit(i)){
			TT[2][i]-=e;
		}
	}
}
///////////////////////////
int main(){
	srand(time(0));
	if(rand()%2){//线段树
	int n;
	fin>>n;
	sign.resize(n+1,0);//确定长度
	int l=n*log((double)n)/log(2.0);//确定长度
	tree.resize(l);//确定长度   省空间
	_build(1,1,n);//创建线段树
	for(int i=1;i<=n;++i){
		int e;
		fin>>e;
		_refresh_up(sign[i],e);//从叶子节点向上更新
	}
	int t;
	fin>>t;
	const string A="ADD";
	for(int i=0;i!=t;++i){//如题
		string txt;
		fin>>txt;
		if(txt==A){
			int l,r,n;
			fin>>l>>r>>n;
			_add(1,l,r,n);
		}else{
			int a,b;
			fin>>a>>b;
			fout<<_sum(1,a,b)<<endl;
		}
	}
	}else{//树状数组
	int n;
	fin>>n;
	TT[0].resize(n+1,0);//vector就是这么用的
	TT[1].resize(n+1,0);//我就是不喜欢直接写具体长度 
	TT[2].resize(n+1,0);//你咬我
	for(int i=0;i!=n;++i){
		int e;
		fin>>e;
		_aadd(0,i+1,0,0,e);//添加原始数据 第三四个0无意义 只是为了配合函数形式
	}
	int N;
	fin>>N;
	const string A="ADD";
	for(int i=0;i!=N;++i){//如题
		string txt;
		fin>>txt;
		if(txt==A){//add
			int l,r,e;
			fin>>l>>r>>e;
			_aadd(1,0,l,r,e);
		}else{//sum
			int l,r;
			fin>>l>>r;
			fout<<_ssum(2,0,l,r)<<endl;
		}
	}
	}
	//-------------------------*/
	#if defined wolf
	cout<<endl<<(double)clock()/CLOCKS_PER_SEC<<'s'<<endl;
	#endif
	return 0;
}
//Designed by wolf
//Sat Nov 22 2014