[HDU4348]To the moon(主席树)

传送门

对于这个题,显然要打lazy标记了,但是lazy标记pushdown的时候肯定会增加一大堆节点,然后就MLE了。(题解这么说的,我其实不会pushdown)

所以,就换另一种方式,把标记直接打到当前区间,把当前区间的父亲节点大小都更新。求区间和的时候把沿途的标记都加起来就可以了。

注意分多钟情况。

——代码

 1 #include <cstdio>
 2 #define ls son[now][0], l, mid
 3 #define rs son[now][1], mid + 1, r
 4 #define LL long long
 5 
 6 using namespace std;
 7 
 8 const int N = 5000005;
 9 
10 int n, m, tot;
11 int rt[N], son[N][2], add[N];
12 LL sum[N];
13 
14 inline void pushup(int now)
15 {
16     sum[now] = sum[son[now][0]] + sum[son[now][1]];
17 }
18 
19 inline void build(int &now, int l, int r)
20 {
21     now = ++tot;
22     add[now] = 0;
23     if(l == r)
24     {
25         scanf("%lld", &sum[now]);
26         return;
27     }
28     int mid = (l + r) >> 1;
29     build(ls);
30     build(rs);
31     pushup(now);
32 }
33 
34 inline void update(int &now, int l, int r, int last, int ql, int qr, int x)
35 {
36     now = ++tot;
37     add[now] = add[last];
38     sum[now] = sum[last];
39     son[now][0] = son[last][0];
40     son[now][1] = son[last][1];
41     sum[now] += (LL)x * (qr - ql + 1);
42     if(l == ql && r == qr)
43     {
44         add[now] += x;
45         return;
46     }
47     int mid = (l + r) >> 1;
48     if(qr <= mid) update(ls, son[now][0], ql, qr, x);
49     else if(ql > mid) update(rs, son[now][1], ql, qr, x);
50     else
51     {
52         update(ls, son[now][0], ql, mid, x);
53         update(rs, son[now][1], mid + 1, qr, x);
54     }
55 }
56 
57 inline LL query(int now, int l, int r, int ql, int qr)
58 {
59     if(l == ql && r == qr) return sum[now];
60     int mid = (l + r) >> 1;
61     LL ret = (LL)add[now] * (qr - ql + 1);
62     if(qr <= mid) return ret + query(ls, ql, qr);
63     else if(ql > mid) return ret + query(rs, ql, qr);
64     else return ret + query(ls, ql, mid) + query(rs, mid + 1, qr);
65 }
66 
67 int main()
68 {
69     int i, x, y, z, now;
70     bool f = 0;
71     char s[5];
72     while(~scanf("%d %d", &n, &m))
73     {
74         if(f) printf("\n");
75         else f = 1;
76         now = tot = 0;
77         build(rt[0], 1, n);
78         for(i = 1; i <= m; i++)
79         {
80             scanf("%s", s);
81             switch(s[0])
82             {
83                 case 'C': scanf("%d %d %d", &x, &y, &z); now++; update(rt[now], 1, n, rt[now - 1], x, y, z); break;
84                 case 'Q': scanf("%d %d", &x, &y); printf("%lld\n", query(rt[now], 1, n, x, y)); break;
85                 case 'H': scanf("%d %d %d", &x, &y, &z); printf("%lld\n", query(rt[z], 1, n, x, y)); break;
86                 case 'B': scanf("%d", &now); break;
87             }
88         }
89     }
90     return 0;
91 }
View Code

 

posted @ 2017-04-25 10:20  zht467  阅读(116)  评论(0编辑  收藏  举报