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, 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
线段树模板:
//线段树最起码包括三个步骤
//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);
}
}
}