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

A Simple Problem with Integers

Time Limit: 5000MS Memory Limit: 131072K
Total Submissions: 112668 Accepted: 35011
Case 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 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.

线段树模板:

//线段树最起码包括三个步骤
//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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值