http://acm.pku.edu.cn/JudgeOnline/problem?id=3468 成段更新,区间求和(要用long long)
2010-08-16 14:06
537 查看
]/* 好不容易AC的, vim这个插件有时海的我好惨的. */ #include <iostream> #include <cstdio> #define LL(x) ((x) << 1) #define RR(x) ((x) << 1 | 1) using namespace std; const int N = 100005; struct Seg_tree{ int l, r; long long val; // 保存一段区间内增加的值 long long sum; // 保存一段区间的和 int mid(){ return (r + l) >> 1; } long long len(){ return (r - l + 1); } }tree[N * 3]; int df ; inline void Build(int l, int r, int node){ tree[node].l = l; tree[node].r = r; tree[node].val = 0; if(l == r){ tree[node].sum = df[l]; return ; } int mid = (l + r) >> 1; Build(l , mid, LL(node)); Build(mid + 1, r, RR(node)); tree[node].sum = tree[LL(node)].sum + tree[RR(node)].sum; } inline void Update(int l, int r, int node, int val){ if(l <= tree[node].l && tree[node].r <= r){ tree[node].val += val; // 增加这个区间的值 tree[node].sum += tree[node].len() * val; // 更改这个区间的和 return ; } if(tree[node].val){// 更改子节点的sum值 和 val tree[LL(node)].sum += tree[node].val * tree[LL(node)].len(); tree[RR(node)].sum += tree[node].val * tree[RR(node)].len(); tree[LL(node)].val += tree[node].val; tree[RR(node)].val += tree[node].val; tree[node].val = 0; } int mid = tree[node].mid(); /* if(l <= mid) Update(l, r, LL(node), val); if(mid < r) Update(l ,r, RR(node), val); */ if(r <= mid){ Update(l, r, LL(node), val); } else if(l > mid){ Update(l, r, RR(node), val); } else{ Update(l , mid, LL(node), val); Update(mid + 1, r, RR(node),val); } tree[node].sum = tree[LL(node)].sum + tree[RR(node)].sum; } inline long long Question(int l, int r, int node){ if(l <= tree[node].l&& tree[node].r <= r){ return tree[node].sum; } if(tree[node].val){ tree[LL(node)].sum += tree[node].val * tree[LL(node)].len(); tree[RR(node)].sum += tree[node].val * tree[RR(node)].len(); tree[LL(node)].val += tree[node].val; tree[RR(node)].val += tree[node].val; tree[node].val = 0; } int mid = tree[node].mid(); if(r <= mid){ return Question(l , r, LL(node)); } else if(l > mid){ return Question(l , r, RR(node)); } else{ return Question(l , mid, LL(node)) + Question(mid + 1, r, RR(node)); } } int main(){ int n, q; while(scanf("%d %d", &n, &q) != EOF){ for(int i = 1; i <= n; i++) scanf("%d", &df[i]); Build(1, n, 1); char str[2]; int a, b, c; while(q--){ scanf("%s", str); if(str[0] == 'Q'){ scanf("%d %d", &a, &b); printf("%lld/n", Question(a, b, 1)); } else{ scanf("%d %d %d", &a, &b, &c); Update(a, b, 1, c); } } } return 0; }
相关文章推荐
- http://acm.pku.edu.cn/JudgeOnline/problem?id=2777 成段更新,区间统计颜色的种类 (用的位运算, 可是写的很搓)
- http://acm.pku.edu.cn/JudgeOnline/problem?id=2528 成段更新,区间统计颜色的种类(离散化处理线段)
- http://acm.pku.edu.cn/JudgeOnline/problem?id=3667 区间更新+求满足长短的最左区间
- http://acm.pku.edu.cn/JudgeOnline/problem?id=1808 二次剩余式
- http://acm.pku.edu.cn/JudgeOnline/problem?id=2407 很水的欧拉
- http://acm.pku.edu.cn/JudgeOnline/problem?id=1284 (原根)
- http://acm.pku.edu.cn/JudgeOnline/problem?id=2409 polya或者burnside
- http://acm.pku.edu.cn/JudgeOnline/problem?id=2891 欧几里德线性同余方程
- http://acm.pku.edu.cn/JudgeOnline/problem?id=2480 欧拉
- http://acm.pku.edu.cn/JudgeOnline/problem?id=1131 八进小数转十进制小数
- http://acm.pku.edu.cn/JudgeOnline/problem?id=2305 大数的b进制数 取模
- http://acm.hdu.edu.cn/showproblem.php?pid=1698 成段更新,总区间求和
- http://acm.hdu.edu.cn/showproblem.php?pid=1166&&线段树区间求和
- Fire Net from http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=2
- http://acm.hunnu.edu.cn/online/?action=problem&type=show&id=10102&courseid=0
- http://acm.hunnu.edu.cn/online/?action=problem&type=show&id=10594&courseid=4
- Crashing Balloon from http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=3
- http://acm.pku.edu.cn/JudgeOnline/
- Post office (区间dp 记忆化搜索) http://acm.zzuli.edu.cn/problem.php?id=1468
- http://acm.hdu.edu.cn/showproblem.php?pid=1166 更新节点,区间求和