poj 3468 小白算法练习 a simple problem with integers 线段树

来源:互联网 发布:简历淘宝美工工作描述 编辑:程序博客网 时间:2024/06/07 06:19

A Simple Problem with Integers

Time Limit: 5000MS Memory Limit: 131072KTotal Submissions: 112668 Accepted: 35011Case Time Limit: 2000MS

Description

You have N integers, A1A2, ... , 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 A1A2, ... , AN. -1000000000 ≤ Ai ≤ 1000000000.
Each of the next Q lines represents an operation.
"C a b c" means adding c to each of AaAa+1, ... , Ab. -10000 ≤ c ≤ 10000.
"Q a b" means querying the sum of AaAa+1, ... , Ab.

Output

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

Sample Input

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

Sample Output

455915

Hint

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

线段树模板:

//线段树最起码包括三个步骤
//1、构造
//2、搜索 | 查找
//3、更新 

int MAX=1000;
struct threadtree{
int val;
};
threadtree tt[MAX];

/*
root:线段树的根节点
arr:用来构造线段树的数组 
start:数组的起始位置
end:数组的结束位置 
*/

//构造 
void build(int root,int arr[],int start,int end){
//如果是叶子节点 

if(start==end){
tt[root].val=arr[start];

else
{
int mid=(start+end)/2;
build(root*2+1,arr,start,mid);
build(root*2+2,arr,mid+1,end);
//那么这里是   不是叶子节点的节点取最小值
tt[root].val=min(tt[root+1].val,tt[root+2].val); 
}

/*
s_start:想要查找起点
s_end:想要查找终点
c_start:正在查找线段树的起点
c_end:正在查找线段树的终点 
*/

//搜索 | 查找
int search(int root,int s_start,int s_end,int c_start,int c_end){
//查询区间与当前区间没有交集 
if(s_start>c_end || s_end<c_start )
return INT_MAX;
//查询区间如果大于当前区间 
if(s_start<=t_start && s_end>=c_end)
{
return tt[root].val;

//查询区间如果小于当前区间就往子树下面搜 
int mid=(c_start+c_end)/2;
//合并区间,因为不可能正正好好的在同一颗子树上 
return min(search(root*2+1,s_start,s_end,c_start,mid),search(root*2+2,s_start,s_end,mid+1,c_end));

//首先是单节点更新 --- 单节点更新过后说的是更新单片叶子,叶子更新过后要更新父节点
/*
c_start:当前线段树的起点 
c_end:当前的线段树的终点 
index:arr数组中的改变值的下标 
doval:想要增加或改变的值 
*/

void update(int root,int c_start,int c_end,int index,int doval){

//index与start相同时就代表找到了

if(c_start==c_end){
if(c_start==index)
tt[root].val+=doval;
return;
}
int mid=(c_start+c_end)/2;
if(index<=mid) 
update(root*2+1,c_start,mid,index,doval);

else update(root*2+2,mid+1,c_end,index,doval);

tt[root].val=min(tt[root*2+1].val,tt[root*2+2].val);

//区间更新【延迟标记还是挺难理解的】

const int MAX=1000;
struct threadtree{
int val;
int addval;//延迟标记 
}; 
threadtree[MAX];
void push_down(int root){
if(tt[root].addval!=0){
tt[root*2+1].addval+=tt[root].addval;
tt[root*2+2].addval+=tt[root].addval;
tt[root*2+1].val+=tt[root].addval;
tt[root*2+2].val+=tt[root].addval;
tt[root].addval=0;
}
}
void build(int root,int arr[],int start,int end){
tt[root].addval=0;//延迟标记初始化为0 
if(start==end){
tt[root].val=arr[start];
return; 
}
else{
int mid=(start+end)/2;
build(root*2+1,arr,start,mid);
build(root*2+2,arr,mid+1,end);

tt[root].val=min(tt[root*2+1].val,tt[root*2+2].val);
}
}
int search(int root,int start,int end,int c_start,int c_end){
if(start>c_end || end<c_start){
return INT_MAX;
}
if(start<=c_start && end>=c_end){
return tt[root].val;
}
push_down(root);
int mid=(c_start+c_end)/2;
return min(search(root*2+1,start,end,c_start,mid),search(root*2+2,start,end,mid,c_end));
}
int update(int root,int start,int end,int c_start,int c_end,int addval){
if(start>c_end || end<c_start){
return INT_MAX;
}
if(start<=c_start && end>=c_end){
tt[root].addval+=addval;
tt[root].val+=addval;
return;
}
push_down(root);
int mid=(c_start+c_end)/2;
update(root*2+1,start,mid,c_start,c_end,addval);
update(root*2+2,mid+1,end,c_start,c_end,addval);

tt[root].val=min(tt[root*2+1].val,tt[root*2+2].val);
}

代码:

#include<iostream>#include<algorithm>#include<cstring>using namespace std;const int MAX=100005;struct tree{long long val;long long mark;}segtree[MAX*4+1];long long sum(long long a,long long b){ //long long !!我被搞了很久return a+b;}void push_down(int root,int range){if(segtree[root].mark!=0){segtree[root*2+1].mark+=segtree[root].mark;segtree[root*2+2].mark+=segtree[root].mark;segtree[root*2+1].val+=(range-(range/2))*segtree[root].mark;//***//segtree[root*2+2].val+=(range/2)*segtree[root].mark;//***//segtree[root].mark=0;}}void build(int root,int arr[],int start,int end){segtree[root].mark=0;if(start==end){segtree[root].val=arr[start];return;}else{int mid=(start+end)/2;build(root*2+1,arr,start,mid);build(root*2+2,arr,mid+1,end);segtree[root].val=sum(segtree[root*2+1].val,segtree[root*2+2].val);}}long long search(int root,int start,int end,int c_start,int c_end){if(start>c_end || end<c_start) return 0;if(start<=c_start && end>=c_end){return segtree[root].val;}push_down(root,c_end-c_start+1);//***//int mid=(c_start+c_end)/2;return sum(search(root*2+1,start,end,c_start,mid),search(root*2+2,start,end,mid+1,c_end));}void update(int root,int start,int end,int c_start,int c_end,int add){if(start>c_end || end<c_start) return;if(start<=c_start && end>=c_end){segtree[root].mark+=add;segtree[root].val+=(c_end-c_start+1)*add;//***//return;}push_down(root,c_end-c_start+1);//***//int mid=(c_start+c_end)/2;update(root*2+1,start,end,c_start,mid,add);update(root*2+2,start,end,mid+1,c_end,add);segtree[root].val=sum(segtree[root*2+1].val,segtree[root*2+2].val);} int main(){//freopen("E:1001.txt","r",stdin);int N,Q;//数组N个数,输入N个数;Q次操作cin>>N>>Q;int arr[MAX];char str[5]="";for(int i=1;i<=N;i++){cin>>arr[i];}build(0,arr,1,N);for(int i=1;i<=Q;i++){cin>>str;if(strcmp(str,"Q")==0){int s,e;cin>>s>>e;cout<<search(0,s,e,1,N)<<endl;}else{int s,e,add;cin>>s>>e>>add;update(0,s,e,1,N,add);}}}

 



阅读全文
0 0