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 }
  • 相关阅读:
    Truck History(poj 1789)
    Highways poj 2485
    117. Populating Next Right Pointers in Each Node II
    116. Populating Next Right Pointers in Each Node
    115. Distinct Subsequences
    114. Flatten Binary Tree to Linked List
    113. Path Sum II
    109. Convert Sorted List to Binary Search Tree
    106. Construct Binary Tree from Inorder and Postorder Traversal
    105. Construct Binary Tree from Preorder and Inorder Traversal
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/6094527.html
Copyright © 2011-2022 走看看