您的位置:首页 > 其它

poj 3468 A Simple Problem with Integers - 线段树

2016-07-12 21:45 246 查看
Description

You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval.

Input

The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000.
The second line contains N numbers, the initial values of A1, A2, ... , AN. -1000000000 ≤ Ai ≤ 1000000000.
Each of the next Q lines represents an operation.
"C a b c" means adding c to each of Aa, Aa+1, ... , Ab. -10000 ≤ c ≤ 10000.
"Q a b" means querying the sum of Aa, Aa+1, ... , Ab.

Output

You need to answer all Q commands in order. One answer in a line.

Sample Input

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

Sample Output

4
55
9
15

Hint

The sums may exceed the range of 32-bit integers.
Source

POJ Monthly--2007.11.25, Yang Yi
(来自http://poj.org/problem?id=3468)

  j讲一下题目大意,就是有n个数和m个操作,操作有2种,一种是C还有一种是Q,C是将[a,b]这个区间内每一个数增加c,而Q是查询[a,b]这个区间的和

这道题没什么可以讲的,线段树直接上

/**
* poj.org
* Problem#3468
*/
#include<iostream>
#include<cstdio>
using namespace std;
typedef long long ll;
ll *a;
/**
* 树节点
*/
typedef class TreeNode{
private:
void init(){
left = NULL;
right= NULL;
sum  = 0;
state= 0;
}
public:
int from;            //区间的开始
int end;             //区间的结束
TreeNode *left;        //左子树
TreeNode *right;    //右子树指针
ll sum;                //这一段的和
ll state;            //延时标记,当非0表示有更新
TreeNode(){
init();
}
TreeNode(int from, int end){
init();
this->from = from;
this->end  = end;
}
}TreeNode;
/**
* 树结构
*/
typedef class Tree{
public:
TreeNode* root;
Tree():root(NULL){}
Tree(int len){
root = build(root, 1, len);
}
void pushUp(TreeNode* node){
if(node->left != NULL && node->right != NULL)
node->sum = node->left->sum + node->right->sum;
}
void pushDown(TreeNode* node){

node->left->state += node->state;
node->left->sum += (node->left->end - node->left->from + 1) * node->state;

node->right->state += node->state;
node->right->sum += (node->right->end - node->right->from + 1) * node->state;

node->state = 0;

}
TreeNode* build(TreeNode* root,int from, int end){
if(from == end){
root = new TreeNode(from, end);
root->sum = a[from];
return root;
}
root = new TreeNode(from, end);
int mid = (from + end)/2;
root->left = build(root->left, from, mid);
root->right = build(root->right, mid + 1, end);
pushUp(root);
return root;
}
void updata(TreeNode* now, int from, int end, ll data){

if(from <= now->from && now->end <= end ){
now->state += data;
now->sum += ( now->end - now->from + 1) * data;
return ;
}
now->sum += (end - from + 1) * data;
if(now->state != 0) pushDown(now);
int mid = (now->from + now->end)/2;
if(end <= mid) updata(now->left, from, end, data);
else if(from > mid) updata(now->right, from, end,data);
else{
updata(now->left, from, mid, data);
updata(now->right, mid + 1, end, data);
}

}
ll query(TreeNode* now, int from, int end){

if(from <= now->from && now->end <= end ) return now->sum;
if(now->state != 0) pushDown(now);
int mid = (now->from + now->end)/2;
if(end <= mid) return query(now->left, from, end);
else if(from > mid) return query(now->right, from, end);
else{
return (query(now->left, from, mid) +
query(now->right, mid + 1, end));
}

}
}Tree;
int n,m;
Tree MyTree;
char c;
int buffer[3];
int main(){
scanf("%d%d",&n,&m);
a = new ll[(const int)(n + 1)];
for(int i = 1;i <= n;i++){
scanf("%lld",&a[i]);
}
MyTree = Tree(n);
for(int i = 1;i <= m;i++){
cin>>c;
if(c == 'C'){
scanf("%d%d%d",&buffer[0],&buffer[1],&buffer[2]);
MyTree.updata(MyTree.root, buffer[0], buffer[1], buffer[2]);
}else{
scanf("%d%d",&buffer[0],&buffer[1]);
printf("%lld\n",MyTree.query(MyTree.root, buffer[0], buffer[1]));
}
}
return 0;
}


另外,原数组的类型最好要用long long

后记:

 一个神奇的问题:原数组int过不了,改成long long提交一次,过了,接着改成int,就Accepted
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: