题目描述:
标准的线段树。给出序列操作,分别为对一段区间增值 和 求某一段区间和。
解题思路:
标准的线段树建树,修改和查询操作。这里要注意的是,对修改操作为了避免修改到叶子节点而导致的超时问题,令修改到对应的区间即可,而此时为了保证该区间下的节点能够意识到自己的值已经被修改了——通过对该区间打延时标记来实现。
附注:有个坑,就是增量得开到64位long long。
代码:
#include
#include
#define N 100001
typedef struct{
int left, right;
long long tab;
long long inc;//标记
}CH;
CH segTree[4*N];
int n,q, num[N];
long long sum;
void buildTree(int l, int r, int index){
segTree[index].left = l;
segTree[index].right = r;
segTree[index].tab = 0;
segTree[index].inc = 0;
if(l!=r){
buildTree(l,(l+r)/2,2*index);
buildTree((l+r)/2+1,r,2*index+1);
}
}
void changeTree(int l, int r, int t, int index){
if(segTree[index].left <= l && segTree[index].right >= r){
//printf("更改区域[%d-%d],增加值%d\n",segTree[index].left,segTree[index].right, (r-l+1)*t);
segTree[index].tab += (r-l+1)*t;
if(!(segTree[index].left == l && segTree[index].right == r)){ //不是恰好符合的区间,继续更新
if(l>(segTree[index].left+segTree[index].right)/2){ // in right area
changeTree(l,r,t,2*index+1);
}else if(r <= (segTree[index].left+segTree[index].right)/2){
changeTree(l,r,t,2*index);
}else{
changeTree(l,(segTree[index].left+segTree[index].right)/2,t,2*index);
changeTree((segTree[index].left+segTree[index].right)/2+1,r,t,2*index+1);
}
}else{ //恰好符合的区间,添加标记
// printf("在区域[%d-%d]添加inc=%d\n",segTree[index].left,segTree[index].right,(r-l+1)*t);
segTree[index].inc += t;
}
}
}
void searchTree(int l, int r, int index){
if(l == segTree[index].left && r == segTree[index].right){
//printf("在[%d-%d]区域,添加tab=%d\n",l,r,segTree[index].tab);
sum += segTree[index].tab;
}else if(l>(segTree[index].left+segTree[index].right)/2){
// printf("在[%d-%d]区域,添加inc=%d\n",segTree[index].left,segTree[index].right,segTree[index].inc*(r-l+1));
sum += segTree[index].inc*(r-l+1);
searchTree(l,r,2*index+1);
}else if(r <= (segTree[index].left+segTree[index].right)/2){
// printf("在[%d-%d]区域,添加inc=%d\n",segTree[index].left,segTree[index].right,segTree[index].inc*(r-l+1));
sum += segTree[index].inc*(r-l+1);
searchTree(l,r,2*index);
}else{
// printf("在[%d-%d]区域,添加inc=%d\n",segTree[index].left,segTree[index].right,segTree[index].inc*(r-l+1));
sum += segTree[index].inc*(r-l+1);
searchTree(l,(segTree[index].left+segTree[index].right)/2,2*index);
searchTree((segTree[index].left+segTree[index].right)/2+1,r,2*index+1);
}
}
main(){
char order[2];
int l, r, c, i;
scanf("%d %d",&n,&q);
buildTree(1,n,1);
for(i=1;i<=n;i++){
scanf("%d",&num[i]);
changeTree(i,i,num[i],1);
}
// printf("----------------------------------\n\n");
for(i=1;i<=q;i++){
scanf("%s",order);
if(strcmp(order,"Q")==0){
sum = 0;
scanf("%d %d",&l, &r);
searchTree(l,r,1);
printf("%lld\n",sum);
}else{
scanf("%d %d %d",&l,&r,&c);
changeTree(l,r,c,1);
}
}
system("pause");
return 0;
}