zoukankan      html  css  js  c++  java
  • 【HDU4348】To The Moon-主席树(可持久化线段树)区间修改+区间询问

    测试地址:To The Moon

    题目大意:维护一个长度为N的数列,支持以下操作:将其中的某个区间内元素加上一个值然后将时间戳+1,询问当前时间戳内某一个区间内元素的和,询问某个时间戳内某一个区间内元素的和,将时间戳重置回某一个前面的时间。

    做法:这道题一看就是主席树了,按照主席树区间修改和区间询问的方法去做就行了。但是这道题有点卡空间,如果空间爆了可以用以下方式减少空间的用量:不用下放标记,只需要在询问时实时记录从根到某个节点路径上所有标记的和,就相当于覆盖在这个节点上的标记了,但是要特别注意这种情况下的pushup,在pushup时不要忘了加上该区间原来的标记即可。最后就是注意数据可能爆int,要用long long来存储区间和。

    题外话:To The Moon这个游戏我当初玩过,在做题时又看到这个还是挺兴奋的^_^,据说还是国人作品,很厉害啊~

    以下是本人代码:

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    int n,m,a[100010],rt[100010],tot,now;
    struct segnode
    {
      int lc,rc;
      long long sum,p;
    }seg[4000010];
    
    void buildtree(int &no,int l,int r)
    {
      no=++tot;
      seg[no].lc=seg[no].rc=seg[no].p=0;
      if (l==r)
      {
        seg[no].sum=a[l];
        return;
      }
      int mid=(l+r)>>1;
      buildtree(seg[no].lc,l,mid);
      buildtree(seg[no].rc,mid+1,r);
      seg[no].sum=seg[seg[no].lc].sum+seg[seg[no].rc].sum;
    }
    
    void modify(int &no,int last,int l,int r,int s,int t,long long c)
    {
      no=++tot;
      seg[no]=seg[last];
      if (l>=s&&r<=t)
      {
        seg[no].p+=c;
    	seg[no].sum+=c*(r-l+1);
    	return;
      }
      int mid=(l+r)>>1;
      if (s<=mid) modify(seg[no].lc,seg[last].lc,l,mid,s,t,c);
      if (t>mid) modify(seg[no].rc,seg[last].rc,mid+1,r,s,t,c);
      seg[no].sum=seg[seg[no].lc].sum+seg[seg[no].rc].sum+(r-l+1)*seg[no].p;
    }
    
    long long query(int no,int l,int r,int s,int t,long long presum)
    {
      if (l>=s&&r<=t) return seg[no].sum+presum*(r-l+1);
      int mid=(l+r)>>1;
      long long sums=0;
      if (s<=mid) sums+=query(seg[no].lc,l,mid,s,t,presum+seg[no].p);
      if (t>mid) sums+=query(seg[no].rc,mid+1,r,s,t,presum+seg[no].p);
      return sums;
    }
    
    int main()
    {
      int t=0;
      while(scanf("%d%d",&n,&m)!=EOF)
      {
        t++;
    	if (t>1) printf("
    ");
        tot=now=0;
        for(int i=1;i<=n;i++)
          scanf("%d",&a[i]);
        buildtree(rt[0],1,n);
        
        for(int i=1;i<=m;i++)
        {
          char op[10];
    	  int a,b,c;
    	  scanf("%s",op);
    	  if (op[0]=='C')
    	  {
    	    scanf("%d%d%d",&a,&b,&c);
    		modify(rt[now+1],rt[now],1,n,a,b,c);
    		now++;
    	  }
    	  if (op[0]=='Q')
    	  {
    	    scanf("%d%d",&a,&b);
    		printf("%lld
    ",query(rt[now],1,n,a,b,0));
    	  }
    	  if (op[0]=='H')
    	  {
    	    scanf("%d%d%d",&a,&b,&c);
    		printf("%lld
    ",query(rt[c],1,n,a,b,0));
    	  }
    	  if (op[0]=='B')
    	  {
    	    scanf("%d",&a);
    		now=a;
    	  }
        }
      }
      
      return 0;
    }
    


  • 相关阅读:
    【SCOI 2011】 糖果
    【POJ 3159】 Candies
    【POJ 1716】 Integer Intervals
    【POJ 2983】 Is the information reliable?
    【POJ 1364】 King
    【POJ 1201】 Intervals
    【POJ 1804】 Brainman
    6月10日省中提高组题解
    【POJ 3352】 Road Construction
    【POJ 1144】 Network
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793809.html
Copyright © 2011-2022 走看看