ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

hdu4348 To the moon(可持久化线段树)

2020-01-15 20:36:38  阅读:385  来源: 互联网

标签:lazy qr 线段 ql mid moon ch now hdu4348


Background
To The Moon is a independent game released in November 2011, it is a role-playing adventure game powered by RPG Maker.
The premise of To The Moon is based around a technology that allows us to permanently reconstruct the memory on dying man. In this problem, we’ll give you a chance, to implement the logic behind the scene.

You‘ve been given N integers A [1], A [2],…, A [N]. On these integers, you need to implement the following operations:

  1. C l r d: Adding a constant d for every {A i | l <= i <= r}, and increase the time stamp by 1, this is the only operation that will cause the time stamp increase.
  2. Q l r: Querying the current sum of {A i | l <= i <= r}.
  3. H l r t: Querying a history sum of {A i | l <= i <= r} in time t.
  4. B t: Back to time t. And once you decide return to a past, you can never be access to a forward edition anymore.
    … N, M ≤ 10 5, |A [i]| ≤ 10 9, 1 ≤ l ≤ r ≤ N, |d| ≤ 10 4 … the system start from time 0, and the first modification is in time 1, t ≥ 0, and won’t introduce you to a future state.
    Input
    n m
    A 1 A 2 … A n
    … (here following the m operations. )
    Output
    … (for each query, simply print the result. )
    Sample Input
10 5
1 2 3 4 5 6 7 8 9 10
Q 4 4
Q 1 10
Q 2 4
C 3 6 3
Q 2 4

2 4
0 0
C 1 1 1
C 2 2 -1
Q 1 2
H 1 2 1

Sample Output

4
55
9
15

0
1

题意:给四种不同操作,对于询问操作输出答案,可持久化线段树的板子题把.
思路:没啥思路,直接写主席树,就是会出好多bug,注意点就是:
在回到之前版本的线段树的时候,把总结点编号也给重置一下避免mle
这虽然和线段树的板子题有点像,但是由于是可持久化的,对于当前版本的这颗树的查询操作我们不能把lazy标记推下去,因为我们如果要推下去的话,那么我们查询之前版本的线段树就会出错。因为当前版本也许会和前面版本线段树共享儿子,把lazy推下去改变儿子节点(设编号为x)的值之后,就会出现查询以前版本也查到了x结点,但是此时结点已经被后面lazy标记影响了。所以查询的时候我们应该直接把lazy影响的值返回,比如查询到一个区间[l,r],这个区间lazy不是0,并且查询区间ql,qr处于这个区间中,那么不推lazy并且又要保持值不变就只能在当前区间就返回一个和:(qr+1-ql) * lazy;
最后就还有一个莫名其妙的就是,在新建一个版本线段树时,采用先找到更新区间然后再用pushup把父结点也更新的做法的话,就会wa,只能够再一遍建树的时候就把每个结点的值都维护好。没想懂为什么。。。

#include<bits/stdc++.h>
#include<iostream>
#include<cstring>
#include<cstdio>
#define mod (10007)
#define middle (l+r)>>1
#define SIZE 1000000+5
#define lowbit(x) (x&(-x))
#define lson (rt<<1)
#define rson (rt<<1|1)
typedef long long ll;
typedef long double ld;
const int inf_max = 0x3f3f3f;
const ll Linf = 9e18;
const int maxn = 100000+10;
const long double E = 2.7182818;
const double eps=0.0001;
using namespace std;
inline int read()
{
    int f=1,res=0;
    char ch=getchar();
    while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
    while(ch>='0'&&ch<='9') { res=res*10+ch-'0' ; ch=getchar(); }
    return f*res;
}

int ls[maxn*25],cnt,rs[maxn*25],root[maxn],n,m,tim;
ll sum[maxn*25],lazy[maxn*25];
void pushup(int rt,int lchd,int rchd) {
    sum[rt] = sum[lchd] + sum[rchd];
}
int build_tree(int l,int r) {
    int rt = cnt++;lazy[rt] = 0;sum[rt] = 0;
    if(l == r) {
        ll t;
        scanf("%lld",&t);
        sum[rt] = t;
        return rt;
    }
    int mid = middle;
    ls[rt] = build_tree(l,mid);
    rs[rt] = build_tree(mid+1,r);
    pushup(rt,ls[rt],rs[rt]);
    return rt;
}
void update(int l,int r,int &now,int last,int ql,int qr,ll val) {
    now = cnt++; sum[now] = sum[last];lazy[now] = lazy[last];ls[now] = ls[last];rs[now] = rs[last];
    sum[now] += (ll)(qr + 1 - ql) * val;
    if(l == ql && r == qr) {
        lazy[now] += val;
        return ;
    }
    int mid = middle;
    if(qr <= mid) {
        update(l,mid,ls[now],ls[last],ql,qr,val);
    }else if(ql > mid ){
        update(mid+1,r,rs[now],rs[last],ql,qr,val);
    }else {
        update(l,mid,ls[now],ls[last],ql,mid,val);
        update(mid+1,r,rs[now],rs[last],mid+1,qr,val);
    }
}
ll query(int l,int r,int now,int ql,int qr) {
    if(l == ql && r == qr) {
        return sum[now];
    }
    int mid = middle;
    if(qr <= mid ) return query(l,mid,ls[now],ql,qr) + lazy[now] * (ll)(qr + 1 - ql);
    else if(ql > mid) return query(mid+1,r,rs[now],ql,qr) + lazy[now] * (ll)(qr + 1 - ql);
    else return query(l,mid,ls[now],ql,mid) + query(mid+1,r,rs[now],mid+1,qr) + lazy[now] * (ll)(qr + 1 - ql);
}
void rst() {
    cnt = 0;tim = 0;
}
int main()
{
    int cas = 0;
    while(~scanf("%d%d",&n,&m)) {
        if(cas++) printf("\n");
        rst();
        root[tim] = build_tree(1, n);
        for (int i = 1; i <= m; i++) {
            char ch;
            int l, r, t;
            ll d;
            cin >> ch;
            if (ch == 'C') {
                tim++;
                scanf("%d%d%lld", &l, &r, &d);
                update(1, n, root[tim], root[tim - 1], l, r, d);
            } else if (ch == 'Q') {
                scanf("%d%d", &l, &r);
                printf("%lld\n", query(1, n, root[tim], l, r));
            } else if (ch == 'H') {
                scanf("%d%d%d", &l, &r, &t);
                printf("%lld\n", query(1, n, root[t], l, r));
            } else if (ch == 'B') {
                scanf("%d", &t);
                tim = t;
                cnt = root[tim + 1];
            }
        }
    }
    return 0;
}
Alstein 发布了30 篇原创文章 · 获赞 8 · 访问量 216 私信 关注

标签:lazy,qr,线段,ql,mid,moon,ch,now,hdu4348
来源: https://blog.csdn.net/qq_44077455/article/details/103994995

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有