(lazy标记,区间修改与查询) A - A Simple Problem with Integers

A - A Simple Problem with Integers

"C a b c" means adding c to each of Aa, Aa+1, ... , Ab. -10000 ≤ c ≤ 10000.
"Q a b" means querying the sum of Aa, Aa+1, ... , Ab.

数据:

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

 AC代码:

const int maxn=1e5+5;
ll a[maxn],n,m;

struct Node{
	ll l,r,su;
	ll lazy; 
}tree[maxn<<2+5];


void build(ll l,ll r,ll k)
{
	tree[k].su=0;
	tree[k].lazy=0;
	tree[k].l=l;
	tree[k].r=r;
	if(l==r){
		tree[k].su=a[l];
		return ;
	}
	else{
		ll mid=(l+r)>>1;
		build(l,mid,k<<1);
		build(mid+1,r,k<<1|1);
		tree[k].su=tree[k<<1].su+tree[k<<1|1].su;
	}
}

void down(int k)//k节点lazy标记下传一位 
{
	if(tree[k].l==tree[k].r) {
		//叶子节点
		//tree[k].su+=tree[k].lazy; 
		return ;
	}
	tree[k<<1].su+=((tree[k<<1].r-tree[k<<1].l+1)*tree[k].lazy);
	tree[k<<1].lazy+=tree[k].lazy;
	tree[k<<1|1].su+=((tree[k<<1|1].r-tree[k<<1|1].l+1)*tree[k].lazy);
	tree[k<<1|1].lazy+=tree[k].lazy;
	tree[k].lazy=0;
}

void update(ll l,ll r,ll k,ll p)//区间修改
{	
	if(tree[k].l>=l && tree[k].r<=r)//不再往下走,lazy标记 
	{//lazy表示改点以下的节点还未修改 
		tree[k].su+=((tree[k].r-tree[k].l+1)*p);
		tree[k].lazy+=p;
		return ;
	}
	//如果节点区间未被全包含,lazy下传
	if(tree[k].lazy) down(k); 
	ll mid=((tree[k].l+tree[k].r)>>1);
	if(l<=mid) update(l,r,k<<1,p);
	if(r>mid) update(l,r,k<<1|1,p);
	tree[k].su=tree[k<<1].su+tree[k<<1|1].su;
} 


ll sum=0;//存区间和 
void summ(ll l,ll r,ll k)//区间和 
{
	if(tree[k].l>=l && tree[k].r<=r)
	{
		sum+=tree[k].su;
		return ;
	}
	if(tree[k].lazy) down(k);
	ll mid=((tree[k].l+tree[k].r)>>1);
	if(l<=mid)
		summ(l,r,k<<1);
	if(r>mid)
		summ(l,r,k<<1|1);
}
/*
void add(ll n,ll x,ll k)//单点修改
{
	if(tree[k].l<=n && n<=tree[k].r)
	{
		tree[k].su+=x;
		if(!(tree[k].l==tree[k].r))
		{
			ll mid=(tree[k].l+tree[k].r)>>1;
			add(n,x,k<<1);
			add(n,x,k<<1|1);
		}
	}
} 
*/
int main() 
{
    scanf("%lld%lld",&n,&m);
    for(ll i=1;i<=n;i++) scanf("%lld",a+i);
  //for(ll i=1;i<=n;i++) scanf("%lld",x),add());//原先代码(超时)
    build(1,n,1);
    char s;
    while(m--)
    {
    	getchar();
    	scanf("%c",&s);
    	ll a,b,c;
    	if(s=='Q')
    	{
    		scanf("%lld%lld",&a,&b);
    		sum=0;
    		summ(a,b,1);
    		printf("%lld\n",sum);
		}
		else{
			scanf("%lld%lld%lld",&a,&b,&c);
			update(a,b,1,c);
		}
	}
    return 0;
}

  

 

->:一直超时,只要去掉单点修改,在build时就将初始数据加入线段树

  还有读数别用cin...

  void build(ll l,ll r,ll k)
  {
      tree[k].su=0;
      tree[k].lazy=0;
      tree[k].l=l;
      tree[k].r=r;
      if(l==r){
          tree[k].su=a[l];//
          return ;
      }
      else{
          ll mid=(l+r)>>1;
          build(l,mid,k<<1);
          build(mid+1,r,k<<1|1);
          tree[k].su=tree[k<<1].su+tree[k<<1|1].su;//省去单点修改
      }  
  }

  

 

 

posted @ 2019-01-21 16:43  liuyongliu  阅读(172)  评论(0编辑  收藏  举报