POJ3468A Simple Problem with Integers

A Simple Problem with Integers

Time Limit: 5000MSMemory Limit: 131072K
Total Submissions: 211861Accepted: 64751
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

BIT

#include <stdio.h>
#include <cctype>
#define ll long long
#define rep(i,a,n) for(int i=a;i<n;i++)
template <typename T>
inline void in(T &x){
	x=0;
	int f=0;char ch=getchar();
	for(;!isdigit(ch);ch=getchar()){f|=ch=='-';}
	for(;isdigit(ch);ch=getchar()){x = (x<<3) + (x<<1) + (ch^48);}
	if(f)x=-x; 
}
inline void out(ll x){
	if(x<0)putchar('-'),x=-x;
	if(x>9)out(x/10);
	putchar(x%10+'0');
}
int n,m,l,r,k;
char p;
const int MAXN = 100001;
int a[MAXN]={0};
ll sum1[MAXN]={0};
ll sum2[MAXN]={0};
void update(int i,int x){
	int d=i;
	while(i<=n){
		sum1[i]+=x;
		sum2[i]+=1LL*(d-1)*x;
		i+=i&-i;
	}
}
ll sum(int i){
	int d=i;
	ll res=0;
	while(i>0){
		res+=sum1[i]*d-sum2[i];
		i-=i&-i;
	}
	return res;
}
int main(){
	in(n);in(m);
	rep(i,1,n+1){
		in(a[i]);
		update(i,a[i]-a[i-1]);
	}
	while(m--){
		p=getchar();
		if(p=='Q'){
			in(l);in(r);
			out(sum(r)-sum(l-1));
			putchar('\n');
		}
		else{
			in(l);in(r);in(k);
			update(l,k);update(r+1,-k);
		}
	}
	return 0;
}

线段树Segment Tree

#include <stdio.h>
#include <cctype>
#include <math.h> 
#define rep(i,a,n) for(int i=a;i<n;i++)
#define ll long long
#define ls(i) (i<<1)
#define rs(i) (i<<1|1)
template <typename T>
inline void in(T &x){
	x=0;
	int f=0;char ch=getchar();
	for(;!isdigit(ch);ch=getchar()){f|=ch=='-';}
	for(;isdigit(ch);ch=getchar()){x = (x<<3) + (x<<1) + (ch^48);}
	if(f)x=-x;
}
template <typename T>
inline void out(T x){
	if(x<0)putchar('-'),x=-x;
	if(x>9)out(x/10);
	putchar(x%10+'0');
}
int n,m,l,r,_k;
char p;
const int M = 100001;
int a[M]={0};
struct node{
	ll lz;
	int l;
	int r;
	ll sum;
	node():lz(0),sum(0){}
}tr[(2<<17)-1];
inline void build(int i,int L,int R){
	tr[i].l=L;tr[i].r=R;
	if(L==R){
		tr[i].sum=a[L-1];
		return;
	}
	int mid=(L+R)>>1;
	build(ls(i),L,mid);
	build(rs(i),mid+1,R);
	tr[i].sum=tr[ls(i)].sum+tr[rs(i)].sum;
}
inline void pushdown(int i){
	if(tr[i].lz){
		tr[ls(i)].lz+=tr[i].lz;
		tr[rs(i)].lz+=tr[i].lz;
		tr[ls(i)].sum+=tr[i].lz*(tr[ls(i)].r-tr[ls(i)].l+1);
		tr[rs(i)].sum+=tr[i].lz*(tr[rs(i)].r-tr[rs(i)].l+1);
		tr[i].lz=0;
	}
}
inline void update(int i,int L,int R,int k){
	if(tr[i].l>=L&&tr[i].r<=R){
		tr[i].sum+=1LL*k*(tr[i].r-tr[i].l+1);
		tr[i].lz+=k;
		return;
	}
	pushdown(i);
	if(tr[ls(i)].r>=L)update(ls(i),L,R,k);
	if(tr[rs(i)].l<=R)update(rs(i),L,R,k);
	tr[i].sum=tr[ls(i)].sum+tr[rs(i)].sum; 
}
inline ll query(int i,int L,int R){
	if(tr[i].l>=L&&tr[i].r<=R)return tr[i].sum;
	if(tr[i].l>R||tr[i].r<L)return 0;
	pushdown(i);
	ll res=0;
	if(tr[ls(i)].r>=L)res+=query(ls(i),L,R);
	if(tr[rs(i)].l<=R)res+=query(rs(i),L,R);
	return res;
} 
int main(){
	in(n);in(m);
	rep(i,0,n)in(a[i]);
	build(1,1,n);
	while(m--){
		p=getchar();in(l);in(r);
		if(p=='Q'){
			out(query(1,l,r));
			putchar('\n');
		}
		else{
			in(_k);
			update(1,l,r,_k);
		}
	}
	return 0;
}
  • 10
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值