线段树区间更新&&求和poj3486
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线段树区间更新&&求和poj3486相关的知识,希望对你有一定的参考价值。
给出了一个序列,你需要处理如下两种询问。 "C a b c"表示给[a, b]区间中的值全部增加c (-10000 ≤ c ≤ 10000)。 "Q a b" 询问[a, b]区间中所有值的和。 Input 第一行包含两个整数N, Q。1 ≤ N,Q ≤ 100000. 第二行包含n个整数,表示初始的序列A (-1000000000 ≤ Ai ≤ 1000000000)。 接下来Q行询问, 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
#include<iostream> #include<stdio.h> #include<cstring> using namespace std; #define MAXSIZE 100005 long long val[MAXSIZE]; long long add[100010<<2]; long long sum[100010<<2]; long long sum1; struct node { long long total; int left; int right; int mark; //延时标记 } tree[MAXSIZE*3]; //下面两种create都可以,选择一种就可 long long create(int root,int left,int right) { add[root]=0; sum[root]=1; tree[root].left=left; tree[root].right=right; if(left==right) return tree[root].total=val[left]; int middle=(left+right)>>1; return tree[root].total=create(root<<1,left,middle)+create(root<<1|1,middle+1,right); } // 参数:询问区间左端点,询问区间右端点,每个位置需要增加的值,当前节点序号 void update(int L, int R, int x, int root) { if (L<=tree[root].left && tree[root].right<= R) { // 当前区间被包含,处理相应附加信息 add[root] += x; // 更新延迟标记 tree[root].total+= x * (tree[root].right-tree[root].left+1); return; // 暂时不用再向下递归 } int mid = (tree[root].left+tree[root].right)>>1; if (add[root]) // 延迟标记不为0,说明有未完成的更新,更新之 { add[root<<1] += add[root]; add[root<<1|1] += add[root]; tree[root<<1].total += add[root] * (mid-tree[root].left+1); tree[root<<1|1].total += add[root] * (tree[root].right-mid); add[root] = 0; // 不要忘了去除延迟标记 } if (L <= mid) // 左子区间中包含有更新区间的部分,需要更新 update(L, R, x, root<<1); if (R > mid) // 右子区间中包含有更新区间的部分,需要更新 update(L, R, x, root<<1|1); tree[root].total = tree[root<<1].total + tree[root<<1|1].total;//从叶子节点向上更新 } /* void find(tree *r,int a,int b){ if(r->left==a&&r->right==b){ sum+=r->data; return; } int mid=(r->left+r->right)>>1; if(b<=mid) find(r->lchild,a,b); else if(a>mid) find(r->rchild,a,b); else{ find(r->lchild,a,mid); find(r->rchild,mid+1,b); } }*/ //long long sum1; long long cal(int root,int a,int b){ if(a<=tree[root].left&&b>=tree[root].right){ return tree[root].total; } int mid=(tree[root].left+tree[root].right)>>1; if(add[root]){ add[root<<1] += add[root]; add[root<<1|1] += add[root]; tree[root<<1].total += add[root] * (mid-tree[root].left+1); tree[root<<1|1].total += add[root] * (tree[root].right-mid); add[root] = 0; // 不要忘了去除延迟标记 } if(b<=mid) return cal(root<<1,a,b); else if(a>mid) return cal(root<<1|1,a,b); else{ return cal(root<<1,a,mid)+cal(root<<1|1,mid+1,b); } } int main(){ int n,q; while(scanf("%d%d",&n,&q)!=EOF){ for(int i=1;i<=n;i++){ scanf("%lld",&val[i]); } memset(sum,0,sizeof(sum)); memset(add,0,sizeof(add)); long long tmp=create(1,1,n); char c; getchar(); int a,b,d; for(int i=1;i<=q;i++){ scanf("%c",&c); if(c==‘C‘){ scanf("%d %d %d",&a,&b,&d); update(a,b,d,1); } else{ scanf("%d%d",&a,&b); sum1=cal(1,a,b); printf("%lld\n",sum1); } getchar(); } } return 0; }
以上是关于线段树区间更新&&求和poj3486的主要内容,如果未能解决你的问题,请参考以下文章
POJ 3468 A Simple Problem with Integers(线段树 单点更新+区间求和 )
poj 3468 A Simple Problem with Integers(线段树+区间更新+区间求和)
POJ 3468 A Simple Problem with Integers(线段树模板之区间增减更新 区间求和查询)