hdu 4348 To the moon

许久没有更博客了...更点最近做的题吧.

hdu 4348 To the moon

  • 此处的主席树还需实现区间加.如果每次都下传 lazy 标记,显然爆炸.
  • 使用标记永久化来处理.更新时一边走一边及时更新,不再向下时在当前节点打一个标记.
  • 询问的时候将从根出发的链上标记全部累加起来计算贡献.
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mp make_pair
#define pii pair<int,int>
inline int read()
{
	int x=0;
	bool pos=1;
	char ch=getchar();
	for(;!isdigit(ch);ch=getchar())
		if(ch=='-')
			pos=0;
	for(;isdigit(ch);ch=getchar())
		x=x*10+ch-'0';
	return pos?x:-x;
}
const int MAXN=1e5+10;
int a[MAXN],rt[MAXN];
struct PreSegTree{
	struct node{
		int ls,rs;
		int f;
		ll sum;
		node()
			{
				ls=rs=0;
				f=0;
				sum=0;
			}
	}tree[MAXN*20];
	int idx,curt;
	void init()
		{
			idx=0;
			curt=0;
		}
	#define root tree[cur]
	#define lson tree[tree[cur].ls]
	#define rson tree[tree[cur].rs]
	inline void pushup(int cur)
		{
			root.sum=lson.sum+rson.sum;
		}
	void BuildTree(int &cur,int l,int r)
		{
			cur=++idx;
			if(l==r)
				{
					root.sum=a[l];
					return;
				}
			int mid=(l+r)>>1;
			BuildTree(root.ls,l,mid);
			BuildTree(root.rs,mid+1,r);
			pushup(cur);
		}
	void update(int lst,int &cur,int l,int r,int L,int R,int v)
		{
			cur=++idx;
			root=tree[lst];
			root.sum+=1LL*v*(min(r,R)-max(l,L)+1);
			if(L<=l && r<=R)
				{
					root.f+=v;
					return;
				}
			int mid=(l+r)>>1;
			if(L<=mid)
				update(tree[lst].ls,tree[cur].ls,l,mid,L,R,v);
			if(R>mid)
				update(tree[lst].rs,tree[cur].rs,mid+1,r,L,R,v);
		}
	ll query(int cur,int l,int r,int L,int R,int tag)
		{
			if(L<=l && r<=R)
				return root.sum+1LL*(r-l+1)*tag;
			int mid=(l+r)>>1;
			ll ans=0;
			if(L<=mid)
				ans+=query(tree[cur].ls,l,mid,L,R,tag+root.f);
			if(R>mid)
				ans+=query(tree[cur].rs,mid+1,r,L,R,tag+root.f);
			return ans;
		}
}T;
int n,m;
int main()
{
	while(~scanf("%d%d",&n,&m))
		{
			T.init();
			for(int i=1;i<=n;++i)
				a[i]=read();
			T.BuildTree(rt[0],1,n);
			while(m--)
				{
					char buf[2];
					scanf("%s",buf);
					if(buf[0]=='C')
						{
							++T.curt;
							int L=read(),R=read(),v=read();
							T.update(rt[T.curt-1],rt[T.curt],1,n,L,R,v);		
						}		
					else if(buf[0]=='Q')
						{
							int L=read(),R=read();
							ll ans=T.query(rt[T.curt],1,n,L,R,0);
							printf("%lld
",ans);
						}
					else if(buf[0]=='H')
						{
							int L=read(),R=read(),t=read();
							ll ans=T.query(rt[t],1,n,L,R,0);
							printf("%lld
",ans);
						}
					else
						{
							assert(buf[0]=='B');
							int t=read();
							T.curt=t;
							T.idx=rt[t+1];
						}
				}
		}
	return 0;
}