A Simple Problem with Integers
这一题就是简单的线段树+懒操作可以解决的。更改区间 查询区间和
由于数据时10^9数量级的 所以sum,a这个操作数要定义成long long型的 其实我在写的过程中把 增加值c也写成long long 了 其实没必要的 不过也没有浪费多少空间的。
其中sum是区间和 a是懒操作标记 就是这个区间上的数都要加上的值 (在search 和update的时候都要进行懒操作)
普通的建树初始化查询和更新,树节点当中存储的是左边界 右边界 区间和 以及懒操作标记
懒操作标记的主要目的就是在更新的时候向下更新 向上更新的操作可以由递归完成的(如注释)
因为这次在查询的时候会不断向下递归查询,与hotel题目不同,需要在search的时候进行更新懒操作。
在更新懒操作标记的时候要给sum 加上 (区间元素个数 * 懒操作数)另外还要向下更新子树结点的懒操作数
还有就是在写这一题之前没有了解牛逼的宏定义 写的代码有点乱的,当时调的也费劲
if(tree[id].l==l&&tree[id].r==r) 至于这里是写成这样还是写成if(tree[id].l>=l&&tree[id].r<=r) 我分析了下其实都是差不多的
其实在查询到一个节点的时候只有两种情况 查询的区间比他小 要么一样大 不可能比他还大 因为若比他大 在上一个父节点的时候已经被拆开了(分别走向左右子树)
其余的感觉没什么可以讲得了,总不能把建树过程详细叙述一遍吧? 嘿嘿
时间复杂度:线段树的修改操作和查询操作都是logN,一共执行Q次修改和查询操作 故时间复杂度为O(QlogN)
空间复杂度:线段树用堆实现 故空间复杂度为O(3N) 有种说法是 3N属于正常,4N属于保守,2N属于拼人品
当然本题用了4N的
#include<cstdio>
#include<cstring>
using namespace std;
#define N 100005
int v[N];
char f[5];
int num1,num2,num3,i,h,k;long long p;
struct node
{
long long sum,a;
int l;
int r;
}tree[N*4];
void build(int id,int l,int r)
{
tree[id].l = l;
tree[id].r = r;
tree[id].a = 0;
if(l==r)
{
tree[id].sum=v[l];
return;
}
else
{
int mid = (l+r)>>1;
build(2*id,l,mid);
build(2*id+1,mid+1,r);
tree[id].sum = tree[id*2].sum + tree[id*2+1].sum;
}
}
long long search(int id,int l,int r)
{
if(tree[id].l==l&&tree[id].r==r)
{
return tree[id].sum;
}
if(tree[id].a) //完成向下更新
{
tree[2*id].a +=tree[id].a;
tree[2*id+1].a+=tree[id].a;
tree[2*id].sum +=tree[id].a*(tree[id*2].r - tree[id*2].l+1);
tree[2*id+1].sum+=(tree[id].a)*(tree[2*id+1].r - tree[2*id+1].l+1);
tree[id].a = 0;
}
int mid = (tree[id].l+tree[id].r)>>1;
if(l>mid)
return search(2*id+1,l,r);
else if(r<=mid)
return search(2*id,l,r);
else
return search(2*id,l,mid)+search(2*id+1,mid+1,r);
}
void update(int id,int l,int r,long long val)
{
if(tree[id].l==l&&tree[id].r==r)
{
tree[id].sum +=(tree[id].r - tree[id].l+1)*val;
tree[id].a += val;
return;
}
if(tree[id].a) //完成向下更新
{
tree[id*2].a +=tree[id].a;
tree[id*2+1].a+=tree[id].a;
tree[2*id].sum+=(tree[2*id].r - tree[2*id].l+1)*tree[id].a;
tree[2*id+1].sum += (tree[2*id+1].r - tree[2*id+1].l+1)*tree[id].a;
tree[id].a = 0;
}
int mid = (tree[id].l+tree[id].r)>>1;
if(l>mid)
update(2*id+1,l,r,val);
else if(r<=mid)
update(2*id,l,r,val);
else
{
update(2*id,l,mid,val);
update(2*id+1,mid+1,r,val);
}
tree[id].sum = tree[id*2].sum + tree[2*id+1].sum; //完成向上更新的主要操作
}
int main()
{
while(scanf("%d%d",&num1,&num2)==2)
{
memset(v,0,sizeof(v));
for(i=1;i<=num1;i++)
scanf("%d",&v[i]);
build(1,1,num1);
while(num2--)
{
scanf("%s",f);
if(f[0]=='Q')
{
scanf("%d%d",&h,&k);
printf("%lld\n",search(1,h,k));
}
else if(f[0]=='C')
{
scanf("%d%d%lld",&h,&k,&p);
if(p==0) continue;
update(1,h,k,p);
}
}
}
return 0;
}