poj3468_A Simple Problem with Integers_线段树_成段更新求和

来源:互联网 发布:神经网络bp算法 编辑:程序博客网 时间:2024/05/23 23:27
//poj3468 A Simple Problem with Integers//线段树成段更新求和//一开始忘记了数据量大,用的cin,结果一直TLE,ORZ。。。//据说要用什么lazy-tag思想,我也不太清楚这算不算//思路就是每个节点加上一个add,如果某一段从left都到right全部都增加val的话,add加上val,然后就不往下更新了//如果之后算的在这范围之内,求和的时候要加上(right-left+1)*add#include <cstdio>#include <cstring>#include <iostream>using namespace std;const int MAXN = 100010;struct Node{int left, right;__int64 add;__int64 sum;}tree[MAXN * 3];int nN, nQ;int arr[MAXN];inline int L(int x){return x << 1;}inline int R(int x){return x << 1 | 1;}void build(int root, int left, int right){tree[root].left = left;tree[root].right = right;if(left == right)tree[root].sum = arr[left];else{int mid = (left + right ) >> 1;build(L(root), left, mid);build(R(root), mid + 1, right);tree[root].sum = tree[L(root)].sum + tree[R(root)].sum;}}__int64 GetSum(int root, int left, int right){if(tree[root].left == left && tree[root].right == right)return tree[root].sum;int mid = (tree[root].left + tree[root].right) >> 1;__int64 add = tree[root].add * (right - left + 1);if(mid >= right)return GetSum(L(root), left, right) + add;else if(mid < left)return GetSum(R(root), left, right) + add;elsereturn GetSum(L(root), left, mid) + GetSum(R(root), mid + 1, right) + add;}void ADD(int root, int left, int right, int val){tree[root].sum += (right - left + 1) * val;//cout << tree[root].left << ' ' <<  tree[root].right << ' ';//printf("%I64d\n", tree[root].sum);if(tree[root].left == left && tree[root].right == right){tree[root].add += val;return;}int mid = (tree[root].left + tree[root].right) >> 1;if(mid >= right)ADD(L(root), left, right, val);else if(mid < left)ADD(R(root), left, right, val);else{ADD(L(root), left, mid, val);ADD(R(root), mid + 1, right, val);}}int main(){while(cin >> nN >> nQ){memset(tree, 0, sizeof(tree));for(int i = 1; i <= nN; i++)scanf("%d", arr + i);build(1, 1, nN);for(int i = 1; i <= nQ; i++){char chOrder;cin >> chOrder;if(chOrder == 'Q'){int nL, nR;scanf("%d%d", &nL, &nR);__int64 ans = GetSum(1, nL, nR);printf("%I64d\n", ans);}else{int nL, nR, nVal;scanf("%d%d%d", &nL, &nR, &nVal);ADD(1, nL, nR, nVal);}}}return 0;}

原创粉丝点击