码迷,mamicode.com
首页 > 其他好文 > 详细

A Simple Problem with Integers POJ - 3468

时间:2021-05-24 10:15:07      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:class   %s   不可   pre   space   加强   需要   return   int   

原题链接
考察:树状数组+差分

上一道题的加强版,但还是结合差分数组
思路:
??操作一:"C a b c"表示给[a, b]区间中的值全部增加c (-10000 ≤ c ≤ 10000)。
??这里还是得用到差分,设b数组为原数组的差分数组,那么此操作就转化为单点修改
??操作二:"Q a b" 询问[a, b]区间中所有值的和。
??这里就不是差分数组了,而是原数组的前缀和.但是如果我们同时维护两个数组:差分数组和原数组是不可能的,这两个操作在差分数组和原数组必然有时间复杂度的冲突.因此考虑其他做法.
??我们不考虑[l,r]区间的和,直接考虑前缀和更为方便.那么就是求\(\sum_{i=1}^r\) \(\sum_{j=1}^i\)b[j] = \(\sum_{i=1}^r\)a[i]
??而这个式子等价于 \(\sum_{i=1}^r\)(r-i+1)b[i].
这个式子很难求前缀和,因为r与i都是不确定的数.而树状数组只能维护b[i],b[i]+c,b[i]*c这种已确定的常量的前缀和.
??但如果我们把(r+1)
b[i]提取出来,即(r+1)b[i]-ib[i]的前缀和.每次操作r都是常数,i是在变化的,所以还需要维护一个i*b[i]的前缀和.

注意一下long long

#include <iostream> 
#include <cstring>
using namespace std;
typedef long long LL;
const int N = 100010,M = 3;//维护b[i],i*b[i] 
int n,m;
LL tr[2][N],b[N];
char s[M];
void insert(int l,int r,int x)
{
	b[l]+=x,b[r+1]-=x;
}
int lowbit(int x)
{
	return x&-x;
}
void add(int k,int idx,LL x)
{
	for(int i=idx;i<=n;i+=lowbit(i)) tr[k][i]+=x;
}
LL ask(int k,int r)
{
	LL res = 0;
	for(int i=r;i;i-=lowbit(i)) res+=tr[k][i];
	return res;
}
LL get(int l,int r)
{
	LL a = (r+1ll)*ask(0,r)-ask(1,r);
	LL b = l*ask(0,l-1)-ask(1,l-1);
	return a-b;
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	{
		int x; scanf("%d",&x);
		insert(i,i,x);
	}
	for(int i=1;i<=n;i++)
		add(0,i,b[i]),add(1,i,(LL)i*b[i]);
	while(m--)
	{
		int r,l,x;
		scanf("%s%d%d",s,&l,&r);
		if(s[0]==‘Q‘)
		{
			printf("%lld\n",get(l,r));
			continue;
		}
		scanf("%d",&x);
		add(0,l,x); add(0,r+1,-x);
		add(1,l,(LL)x*l); add(1,r+1,-(LL)x*(r+1));
	}
	return 0;
}

A Simple Problem with Integers POJ - 3468

标签:class   %s   不可   pre   space   加强   需要   return   int   

原文地址:https://www.cnblogs.com/newblg/p/14770886.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!