ST
时间限制:1000 ms | 内存限制:65535 KB
难度:1
- 描述
-
“麻雀”lengdan用随机数生成了后台数据,但是笨笨的他被妹纸的问题给难住了。。。已知lengdan生成了N(1=<N<=10005)个随机整数,妹子对这些数可能有以下几种操作或询问:
1,A a b c 表示给区间a到b内每个数都加上c;
2,S a b 表示输出区间a到b内的和;
3,Q a b 表示区间a到b内的奇数的个数;
为了使妹纸不口渴,所以我们决定妹纸的询问次数少一点,即(1=<M<=10000,M为询问次数)。
- 输入
-
多组测试数据。
每组测试数据第一行包含两个数N,M,表示N个整数,执行M次询问或操作。
紧接着一行输入N个整数,输入数据保证在int范围内。
接下来M行,每行输入一种操作。
- 输出
- 每次对于操作2和3,输出结果。
- 样例输入
-
5 5 1 2 3 4 5 Q 1 4 S 1 5 A 1 4 1 S 1 5 Q 2 5
- 样例输出
-
2 15 19 3
- 简单的线段树成段更新+区间求和,只是附加了求区间内的奇数个数。由于之前没有写过线段树成段更新的题目,导致因为一条向下更新的语句忘记写,调了一个上午才发现错误。
-
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long LL; const int N = 10010; #define lson l, mid, root<<1 #define rson mid+1, r, root<<1|1 struct node { int l, r; LL sum, odd, add; }a[N<<2]; void PushUp(int root) { a[root].sum = a[root<<1].sum + a[root<<1|1].sum; a[root].odd = a[root<<1].odd + a[root<<1|1].odd; } void PushDown(int len, int root) { if(a[root].add) { a[root<<1].add += a[root].add; a[root<<1|1].add += a[root].add; a[root<<1].sum += LL(len - (len>>1)) * a[root].add; a[root<<1|1].sum += LL(len>>1) * a[root].add; if(a[root].add % 2 == 1) { a[root<<1].odd = len - (len>>1) - a[root<<1].odd; a[root<<1|1].odd = (len>>1) - a[root<<1|1].odd; } a[root].add = 0; } } void build_tree(int l, int r, int root) { a[root].l = l; a[root].r = r; a[root].add = 0; a[root].odd = 0; if(l == r) { scanf("%lld",&a[root].sum); if(a[root].sum % 2 == 1) a[root].odd = 1; return; } int mid = (l + r) >> 1; build_tree(lson); build_tree(rson); PushUp(root); } void update(int l, int r, int root, LL k) { if(l <= a[root].l && r >= a[root].r) { a[root].add += k; a[root].sum += LL(a[root].r - a[root].l + 1) * k; if(k % 2 == 1) a[root].odd = (a[root].r - a[root].l + 1) - a[root].odd; return; } PushDown(a[root].r - a[root].l + 1, root); int mid = (a[root].l + a[root].r) >> 1; if(l <= mid) update(l, r, root<<1, k); if(r > mid) update(l, r, root<<1|1, k); PushUp(root); } LL Query(int l, int r, int root, char ch) { if(l <= a[root].l && r >= a[root].r) { if(ch == 'Q') return a[root].odd; else if(ch == 'S') return a[root].sum; } PushDown(a[root].r - a[root].l + 1, root); LL ans = 0; int mid = (a[root].l + a[root].r) >> 1; if(l <= mid) ans += Query(l, r, root<<1, ch); if(r > mid) ans += Query(l, r, root<<1|1, ch); return ans; } int main() { int n, m, i, x, y; LL z; char ch[5]; while(~scanf("%d%d",&n,&m)) { build_tree(1, n, 1); while(m--) { scanf("%s",ch); if(ch[0] == 'A') { scanf("%d%d%lld",&x,&y,&z); update(x, y, 1, z); } else { scanf("%d%d",&x,&y); printf("%lld\n", Query(x, y, 1, ch[0])); } } } return 0; }
NYOJ 1068 ST(线段树之 成段更新+区间求和)
时间: 2024-12-16 21:19:14