HDU4348 To the moon

Posted SilverNebula

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU4348 To the moon相关的知识,希望对你有一定的参考价值。

Time Limit: 2000MS   Memory Limit: 65536KB   64bit IO Format: %I64d & %I64u

Description

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 
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

Source

 

可持久化线段树模板题。

对于不同的时间建立不同的新结点,新结点按照线段树的规则连接各个被修改的结点的新址(修改时不在原结点修改,而是新建一个结点(类似于分层图什么的)),没有修改的区域就直接链接到旧树的结点(因此不能用root*2 root*2+1的方式算结点,而要用数组模拟指针记录子结点标号)。

由于新层和旧层修改的值不一样,所以lazy标记是不能持久化的,一层的lazy只能在一层用。具体的解决方法见代码。

↑看到有大神说lazy标记持久化的方法是,对每个lazy记录时间戳,只有其标记时间与当前所要求的状态的时间相同时,才计算。然而看上去好麻烦。

 

代码基本靠抄。

 

看到有人说这题卡内存,就特意把数组开小了,结果依旧MLE。折腾一个多小时无果,怒把数组开到300w,居然A了。

↑想了想,大概MLE是因为动态申请新节点时,因为t数组越界,申请到了超大的节点值,直接炸掉内存,所以MLE而不是RE。

感到内存学问博大精深。

 

 1 /*by SilverN*/
 2 #include<algorithm>
 3 #include<iostream>
 4 #include<cstring>
 5 #include<cstdio>
 6 #include<cmath>
 7 #include<vector>
 8 #define LL long long
 9 #define mid (l+r)/2
10 using namespace std;
11 const int mxn=100010;
12 int read(){
13     int x=0,f=1;char ch=getchar();
14     while(ch<0 || ch>9){if(ch==-)f=-1;ch=getchar();}
15     while(ch>=0 && ch<=9){x=x*10+ch-0;ch=getchar();}
16     return x*f;
17 }
18 int n,m;
19 int data[mxn];
20 struct node{
21     int lc,rc;
22     LL sum,mk;
23 }t[3000010];
24 int root[mxn];
25 int nct=0;
26 int ntime=0;
27 void Build(int l,int r,int &rt){
28     t[++nct]=t[rt];
29     rt=nct;
30     if(l==r){
31         t[rt].sum=data[l];
32         return;
33     }
34     Build(l,mid,t[rt].lc);
35     Build(mid+1,r,t[rt].rc);
36     t[rt].sum=t[t[rt].lc].sum+t[t[rt].rc].sum;
37     return;
38 }
39 void add(int L,int R,int v,int l,int r,int &rt){
40     t[++nct]=t[rt];
41     rt=nct;
42     t[rt].sum+=(LL)v*(min(R,r)-max(l,L)+1);
43     if(L<=l && r<=R){
44         t[rt].mk+=v;
45         return;
46     }
47     if(L<=mid)add(L,R,v,l,mid,t[rt].lc);
48     if(R>mid)add(L,R,v,mid+1,r,t[rt].rc);
49     return;
50 }
51 LL query(int L,int R,int l,int r,int rt){
52     if(L<=l && r<=R)return t[rt].sum;
53     LL res=t[rt].mk*1LL*(min(R,r)-(max(L,l))+1);
54     if(L<=mid)res+=query(L,R,l,mid,t[rt].lc);
55     if(R>mid)res+=query(L,R,mid+1,r,t[rt].rc);
56     return res;
57 }
58 int main(){
59     char op[3];
60     int i,j,x,y,a;
61     while(~scanf("%d%d",&n,&m)){
62         ntime=0;nct=0;
63         for(i=1;i<=n;i++)
64             data[i]=read();
65         Build(1,n,root[0]);
66         for(i=1;i<=m;i++){
67             scanf("%s",op);
68             switch(op[0]){
69                 case Q:{
70                     x=read();y=read();
71                     printf("%lld\n",query(x,y,1,n,root[ntime]));
72                     break;
73                 }
74                 case C:{
75                     x=read();y=read();a=read();
76                     ++ntime;
77                     root[ntime]=root[ntime-1];
78                     add(x,y,a,1,n,root[ntime]);
79                     break;
80                 }
81                 case H:{
82                     x=read();y=read();a=read();
83                     printf("%lld\n",query(x,y,1,n,root[a]));
84                     break;
85                 }
86                 case B:{
87                     ntime=read();
88                     break;
89                 }
90             }
91         }
92     }
93     return 0;
94 }

 

以上是关于HDU4348 To the moon的主要内容,如果未能解决你的问题,请参考以下文章

hdu 4348 To the moon

HDU - 4348 To the moon

hdu 4348 To the moon (主席树)

hdu 4348 To the moon

hdu 4348 To the moon (主席树 区间更新)

[HDU4348]To the moon(主席树+标记永久化)