zoukankan      html  css  js  c++  java
  • 【HDU

    BUPT2017 wintertraining(15) #8G

    题意

    给一个数组a,有n个数,m次操作。(N, M ≤ 10^5, |A i| ≤ 10^9, 1 ≤ l ≤ r ≤ N, |d| ≤ 10^4)
    操作有四种,
    C l r d:更新区间[l,r],值都加上d,并且时间前进1
    Q l r:查询[l,r]的区间和
    H l r t:查询t时刻的区间和
    B t:回到t时刻(一定是历史时刻),且t时刻之后的操作都作废了。

    题解

    这道题的关键是怎么更新区间和。
    本来线段树更新区间和要push down也就是把懒惰标记下移,但是这样,整个修改区间都需要新建线段树的节点,空间不够。
    所以考虑在查询的时候传参数下去,也就是一路加上大区间的lazy值,这样就不用push down了。

    代码

    #include <cstdio>
    #include <cstring>
    #define N 100005
    #define M (N*25)
    typedef long long ll;
    namespace PST{
    	int T[N],lson[M],rson[M],tot,n;
    	ll sum[M], lz[M];
    	void init(int _n){
    		tot=0;
    		n=_n;
    		memset(sum,0,sizeof sum);
    		memset(lz,0,sizeof lz);
    	}
    	void push_up(int root,int l,int r){
    		sum[root]=sum[lson[root]]+sum[rson[root]]+lz[root]*(r-l+1);
    	}
    	int build(int l,int r){
    		int root=++tot;
    		if(l==r){
    			scanf("%lld",sum+tot);
    			return tot;
    		}
    		int mid=l+r>>1;
    		lson[root]=build(l,mid);
    		rson[root]=build(mid+1,r);
    		push_up(root,l,r);
    		return root;
    	}
    	int update(int root,int l,int r,int L,int R,int val){
    		int newroot=++tot;
    		lson[newroot]=lson[root];
    		rson[newroot]=rson[root];
    		lz[newroot]=lz[root];
    		if(L<=l&&r<=R){
    			sum[newroot]=sum[root]+(ll)val*(r-l+1);
    			lz[newroot]+=val;
    			return newroot;
    		}
    		int mid=l+r>>1;
    		if(L<=mid)
    			lson[newroot]=update(lson[root],l,mid,L,R,val);
    		if(R>mid)
    			rson[newroot]=update(rson[root],mid+1,r,L,R,val);
    		push_up(newroot,l,r);
    		return newroot;
    	}
    	ll query(int root,int l,int r,int L,int R,ll add){
    		if(L<=l&&r<=R){
    			return sum[root]+(add)*(r-l+1);
    		}
    		int mid=l+r>>1;
    		ll ans=0;
    		if(L<=mid)
    			ans+=query(lson[root],l,mid,L,R,lz[root]+add);
    		if(R>mid)
    			ans+=query(rson[root],mid+1,r,L,R,lz[root]+add);
    		return ans;
    	}
    }
    int main(){
    	int n,m;
    	while(~scanf("%d%d",&n,&m)){
    		int now;
    		PST::init(n);
    		PST::T[now=0]=PST::build(1,n);
    		for(int i=0;i<m;++i){
    			char op;
    			int l,r,t,d;
    			scanf(" %c",&op);
    			if(op=='Q'){
    				scanf("%d%d",&l,&r);
    				printf("%lld
    ",PST::query(PST::T[now],1,n,l,r,PST::lz[PST::T[now]]));
    			}else if(op=='H'){
    				scanf("%d%d%d",&l,&r,&t);
    				printf("%lld
    ",PST::query(PST::T[t],1,n,l,r,PST::lz[PST::T[t]]));
    			}else if(op=='B'){
    				scanf("%d", &now);
    				PST::tot=PST::T[now+1]-1;
    			}else if(op=='C'){
    				scanf("%d%d%d",&l,&r,&d);
    				int tmp=now;
    				PST::T[++now]=PST::update(PST::T[tmp],1,n,l,r,d);
    			}
    		}
    	}
    }
    
  • 相关阅读:
    史上最简洁的handler原理解释
    handler解惑
    Http中get和post的区别
    使用软引用缓存Bitmap
    Request头和Response头
    DNS编程实验--域名与IP的相互转换
    CString与string
    C++ string占多少个字节测试
    java中类的继承性和多态性实例
    java寻找html文件中的标签
  • 原文地址:https://www.cnblogs.com/flipped/p/HDU4348.html
Copyright © 2011-2022 走看看