Light OJ 1411 Rip Van Winkle`s Code 线段树成段更新
时间:2014-07-13 18:04:35
收藏:0
阅读:320
题目来源:Light OJ 1411 Rip Van Winkle`s Code
题意:3中操作 1种查询 求区间和 其中每次可以把一段区间从左到右加上1,2,3,。。。或者从右到左加上。。。3,2,1 或者把某个区间的数都置为v
思路:我是加了6个域
add是这段区间每个数都要加上add add是这么来的 对与123456。。。这个等差数列 可能要分为2个区间 那么我就分成123和123 两个右边的等差数列每个数还应该加上3 所以右区间add加3
v是这个区间都要置为v 他的优先级最高
b是代表这个区间有多少个递增的等差数列
c是代表这个区间有多少个递减的等差数列
sum是区间和
f为真说明要执行C 因为v可以是正和负还可以是0
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 250010; typedef long long LL; struct node { LL sum, add, v, b, c; bool f; }a[maxn<<2]; void build(int l, int r, int rt) { a[rt].sum = 0; a[rt].add = 0; a[rt].b = 0; a[rt].c = 0; a[rt].f = false; if(l == r) return; int m = (l + r) >> 1; build(l, m, rt<<1); build(m+1, r, rt<<1|1); } void pushdown(int rt, int l, int r) { LL k = (LL)(r-l+1); //printf("%d %d %lld\n", l, r, a[rt].v); if(a[rt].f) { a[rt<<1].sum = (LL)a[rt].v*(k-(k>>1)); a[rt<<1|1].sum = (LL)a[rt].v*(k>>1); a[rt<<1].v = a[rt<<1|1].v = a[rt].v; a[rt<<1].f = a[rt<<1|1].f = true; a[rt].f = false; a[rt<<1].b = a[rt<<1|1].b = 0; a[rt<<1].c = a[rt<<1|1].c = 0; a[rt<<1].add = a[rt<<1|1].add = 0; } LL s1 = (k-(k>>1)); LL s2 = (k>>1); if(a[rt].b) { a[rt<<1].sum += (LL)a[rt].b*(1+s1)*s1/2; a[rt<<1|1].sum += (LL)a[rt].b*(1+s2)*s2/2+(LL)s2*s1*a[rt].b; a[rt<<1].b += a[rt].b; a[rt<<1|1].b += a[rt].b; a[rt<<1|1].add += (LL)s1*a[rt].b; a[rt].b = 0; } if(a[rt].c) { a[rt<<1].sum += (LL)a[rt].c*(1+s1)*s1/2+(LL)s2*s1*a[rt].c; a[rt<<1|1].sum += (LL)a[rt].c*(1+s2)*s2/2; a[rt<<1].c += a[rt].c; a[rt<<1|1].c += a[rt].c; a[rt<<1].add += (LL)s2*a[rt].c; a[rt].c = 0; } if(a[rt].add) { a[rt<<1].sum += (LL)a[rt].add*(k-(k>>1)); a[rt<<1|1].sum += (LL)a[rt].add*(k>>1); a[rt<<1].add += a[rt].add; a[rt<<1|1].add += a[rt].add; a[rt].add = 0; } } void update(int x, int y, int l, int r, int rt, LL add, LL v, char c) { //puts("we"); if(l == x && r == y) { if(c == 'A') { /*if(a[rt].f) { a[rt].sum = (LL)(r-l+1)*v; //a[rt].f = false; }*/ a[rt].sum += (LL)(r-l+1)*(r-l+1+1)/2; a[rt].b++; a[rt].sum += (LL)add*(r-l+1); a[rt].add += add; //printf("%d %d %d %lld\n", l, r, a[rt].b, a[rt].sum); } else if(c == 'B') { /*if(a[rt].f) { a[rt].sum = (LL)(r-l+1)*v; //a[rt].f = false; }*/ a[rt].sum += (LL)(r-l+1)*(r-l+1+1)/2; a[rt].c++; a[rt].sum += (LL)add*(r-l+1); a[rt].add += add; } else if(c == 'C') { a[rt].f = true; a[rt].add = 0; a[rt].sum = (LL)(r-l+1)*v; a[rt].b = 0; a[rt].c = 0; a[rt].v = v; } return; } int m = (l + r) >> 1; pushdown(rt, l, r); if(y <= m) { update(x, y, l, m, rt<<1, add, v, c); } else if(x > m) { update(x, y, m+1, r, rt<<1|1, add, v, c); } else { if(c == 'A') { update(x, m, l, m, rt<<1, add, v, c); update(m+1, y, m+1, r, rt<<1|1, add+(m-x+1), v, c); } else if(c == 'B') { update(x, m, l, m, rt<<1, add+(y-m), v, c); update(m+1, y, m+1, r, rt<<1|1, add, v, c); } else if(c == 'C') { //puts("as"); update(x, m, l, m, rt<<1, add, v, c); update(m+1, y, m+1, r, rt<<1|1, add, v, c); } } a[rt].sum = a[rt<<1].sum + a[rt<<1|1].sum; } LL query(int x, int y, int l, int r, int rt) { if(x == l && y == r) { //printf("**%d %d %lld\n", l, r, a[rt].sum); return a[rt].sum; } pushdown(rt, l, r); int m = (l + r) >> 1; LL ans = 0; if(y <= m) ans += query(x, y, l, m, rt<<1); else if(x > m) ans += query(x, y, m+1, r, rt<<1|1); else ans = query(x, m, l, m, rt<<1) + query(m+1, y, m+1, r, rt<<1|1); a[rt].sum = a[rt<<1].sum + a[rt<<1|1].sum; return ans; } int main() { int cas = 1; int T; scanf("%d", &T); while(T--) { int n = 250000; int q; scanf("%d", &q); printf("Case %d:\n", cas++); build(1, n, 1); while(q--) { char s[10]; scanf("%s", s); if(s[0] == 'A') { int x, y; scanf("%d %d", &x, &y); update(x, y, 1, n, 1, 0, 0, 'A'); } else if(s[0] == 'B') { int x, y; scanf("%d %d", &x, &y); update(x, y, 1, n, 1, 0, 0, 'B'); } else if(s[0] == 'C') { int x, y; LL w; scanf("%d %d %lld", &x, &y, &w); update(x, y, 1, n, 1, 0, w, 'C'); } else { int x, y; scanf("%d %d", &x, &y); printf("%lld\n", query(x, y, 1, n, 1)); } } } return 0; } /* 10 B 1 4 A 1 4 S 2 2 B 1 3 C 1 4 1 B 1 4 C 3 3 3 A 2 3 S 2 3 B 3 3 */
评论(0)