| ||||||||||
Online Judge | Problem Set | Authors | Online Contests | User | ||||||
---|---|---|---|---|---|---|---|---|---|---|
Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest | Log Out Mail:0(0) Login Log Archive |
Language:Default A Simple Problem with Integers
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. Output You need to answer all Q commands in order. One answer in a line. Sample Input Sample Output Hint The sums may exceed the range of 32-bit integers. Source POJ Monthly--2007.11.25, Yang Yi |
[Submit] [Go Back] [Status] [Discuss]
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator
BIT 模板题
题目大意:
给你n个数,q次操作。随后输入n个数。
每次操作有一个字符op,若op为C,则随后的三个数 l , r , x ;代表将[l,r]区间的所有数加上x;
若op为Q,则随后的两个数l,r;代表询问[l,r]区间的区间和。
思路:
用两个数组来维护该数据。
data[i] 代表i节点所维护区间属于值都应该加的值
datb[i] 代表i节点部分区间应加的值(最多有一个,当为两个时,该节点已满。应交给data[i]维护)
不断递归,若当前节点所维护的区间在询问的区间内,则加上这个值乘以区间长度以及节点区间内部分数值应加的值。
# include <iostream>
# include <cstdio>
# define ll long long
using namespace std;
const int DAT_SIZE = (1<<18)-1;
const int MAX_Q = 1e5+50;
const int MAX_N = 1e5+50;
int N,Q;
int A[MAX_N];
char T[MAX_Q];
int L[MAX_Q],R[MAX_Q],X[MAX_Q];
//data[i] 代表i节点所维护区间属于值都应该加的值
//datb[i] 代表i节点部分区间应加的值(最多有一个,当为两个时,该节点已满。应交给data[i]维护)
ll data[DAT_SIZE]={0},datb[DAT_SIZE]={0};
void add(int a,int b,int x,int k,int l,int r)
{
//[a,b]包含[l,r]
if(a<=l&&r<=b)
{
data[k]+=x;//储存该区间应加的值
}
else if(l<b&&a<r) //当节点维护的区间
{
//求交集 [a,b]^[l,r]长度 并算出该长度所加值得总和(该节点的区间只有一个数要+x,因此需要另一个数组来维护)
datb[k]+=(min(b,r)-max(a,l))*(ll)x;
//递归的将data[l,r]在[a,b]中的元素标记为应+x
add(a,b,x,k*2+1,l,(l+r)/2);
add(a,b,x,k*2+2,(l+r)/2,r);
}
}
ll sum(int a,int b,int k,int l,int r)
{
if(a<=l&&r<=b)//[a,b]包含[l,r]
return data[k]*(r-l)+datb[k];// 该区间整体应加的值 + 某个数单独应加的值
else if(b>l&&r>a)
{
ll res=(min(b,r)-max(a,l))*data[k];//k节点维护区间应加的值
res+=sum(a,b,k*2+1,l,(l+r)/2);
res+=sum(a,b,k*2+2,(l+r)/2,r);
return res;
}
else
return 0;
}
void solve()
{
for(int i=0;i<N;i++)
add(i,i+1,A[i],0,0,N);
for(int i=0;i<Q;i++)
if(T[i]=='Q')
printf("%lld\n",sum(L[i]-1,R[i],0,0,N));
else
add(L[i]-1,R[i],X[i],0,0,N);
}
int main()
{
cin>>N>>Q;
for(int i=0;i<N;i++)
scanf("%d",&A[i]);
for(int i=0;i<Q;i++)
{
getchar();
scanf("%c",&T[i]);
if(T[i]=='Q')
scanf("%d%d",&L[i],&R[i]);
else
scanf("%d%d%d",&L[i],&R[i],&X[i]);
}
solve();
}