标签: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