HDU_4348

    用可持久化线段树就可以实现O(1)的back操作,同时如果想效率比较高的话,推荐用单点修改+区间查询的模式替代下传标记的区间修改+区间查询的模式来完成对区间和的查询。

    至于如何不下传标记就能完成区间修改和区间求和可以参考ZKW的《统计的力量--线段树》的第59~60页。

#include<stdio.h>
#include<string.h>
#define MAXD 100010
typedef long long LL;
int N, M, node, T[MAXD], np[MAXD];
LL A[MAXD];
struct SegTree
{
    int ls, rs;
    LL d, nd;
}st[2560000];
namespace ST
{
    int build(int x = 1, int y = N)
    {
        int cur = ++ node, mid = x + y >> 1;
        st[cur].d = st[cur].nd = 0;
        if(x < y) st[cur].ls = build(x, mid), st[cur].rs = build(mid + 1, y);
        return cur;
    }
    int insert(int pre, int k, int d)
    {
        int t = ++ node, cur = t, x = 1, y = N;
        for(;;)
        {
            st[cur].d = st[pre].d + d, st[cur].nd = st[pre].nd + (LL)k * d;
            if(x == y) break;
            int mid = x + y >> 1;
            if(k <= mid)
            {
                st[cur].ls = ++ node, st[cur].rs = st[pre].rs;
                cur = node, pre = st[pre].ls, y = mid;
            }
            else
            {
                st[cur].rs = ++ node, st[cur].ls = st[pre].ls;
                cur = node, pre = st[pre].rs, x = mid + 1;
            }
        }
        return t;
    }
}
void init()
{
    int i;
    A[0] = 0;
    for(i = 1; i <= N; i ++) scanf("%I64d", &A[i]), A[i] += A[i - 1];
    node = 0, T[0] = ST::build(), np[0] = node;
}
LL query(int k, int t)
{
    int cur = T[t], x = 1, y = N;
    LL d = 0, nd = 0;
    if(k == 0) return 0;
    for(;;)
    {
        if(x == y)
        {
            d += st[cur].d, nd += st[cur].nd;
            break;
        }
        int mid = x + y >> 1;
        if(k <= mid) cur = st[cur].ls, y = mid;
        else
        {
            d += st[st[cur].ls].d, nd += st[st[cur].ls].nd;
            cur = st[cur].rs, x = mid + 1;
        }
    }
    return A[k] + k * d - nd + d;
}
void solve()
{
    int i, x, y, t, d, cur = 0;
    char op[5];
    for(i = 0; i < M; i ++)
    {
        scanf("%s", op);
        if(op[0] == 'C')
        {
            scanf("%d%d%d", &x, &y, &d);
            ++ cur;
            T[cur] = ST::insert(T[cur - 1], x, d);
            if(y < N) T[cur] = ST::insert(T[cur], y + 1, -d);
            np[cur] = node;
        }
        else if(op[0] == 'Q')
        {
            scanf("%d%d", &x, &y);
            printf("%I64d\n", query(y, cur) - query(x - 1, cur));
        }
        else if(op[0] == 'H')
        {
            scanf("%d%d%d", &x, &y, &t);
            printf("%I64d\n", query(y, t) - query(x - 1, t));
        }
        else
            scanf("%d", &t), cur = t, node = np[t];    
    }
}
int main()
{
    int t = 0;
    while(scanf("%d%d", &N, &M) == 2)
    {
        init();
        if(t ++) printf("\n");
        solve();    
    }
    return 0;    
}

 

 

posted on 2012-09-08 10:39  Staginner  阅读(857)  评论(0编辑  收藏  举报