zoukankan      html  css  js  c++  java
  • 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
    ",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
    ",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 }
  • 相关阅读:
    第一次个人编程作业:我的分数我做主
    第一次作业
    finalshell编码问题
    个人总结-超越平台期
    第一次结对作业
    第二次编程作业代码互改
    第一次个人编程作业
    随笔001
    热是热,很值得—-2019北航暑期软件工程培训感受
    培训第二天------团队协作个人小结
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/6094527.html
Copyright © 2011-2022 走看看