zoukankan      html  css  js  c++  java
  • 【洛谷P3368】【模板】树状数组2【树状数组】

    题目大意:

    题目链接:https://www.luogu.org/problemnew/show/P3368
    已知一个数列,你需要进行下面两种操作:

    1. 将某区间每一个数数加上xx
    2. 输出某一个数

    思路:

    树状数组只支持单点修改,对于区间修改,单点查询应该如和完成呢?
    可以考虑前缀和。每次将一个区间[l,r][l,r]加上xx时,就将a[l]+=xa[l]+=xa[r+1]=xa[r+1]-=x,这样如果将aa数组取前缀和,得到的就还是将区间[l,r][l,r]xx
    那么就可以用最基本的树状数组来求解了。


    代码:

    #include <cstdio>
    #define ll long long
    using namespace std;
    
    int n,m,w,x,y;
    ll a[500001],c[500001],z;
    
    void add(int x,ll y)  //修改
    {
    	for (;x<=n;x+=x&-x) c[x]+=y;
    }
    
    ll ask(int x)  //查询
    {
    	ll ans=0;
    	for (;x;x-=x&-x) ans+=c[x];
    	return ans;
    }
    
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for (int i=1;i<=n;i++)
    	{
    		scanf("%d",&a[i]);
    		add(i,a[i]-a[i-1]);  //保持前缀和为a数组
    	} 
    	while (m--)
    	{
    		scanf("%d",&w);
    		if (w==1)  
    		{
    			scanf("%d%d%d",&x,&y,&z);
    			add(x,z);
    			add(y+1,-z);  //前缀和
    		}
    		else
    		{
    			scanf("%d",&x);
    			printf("%d\n",ask(x));
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    UVA10891
    UVA10453
    UVA 10201
    UVA10154
    UVA11137
    UVA10617
    UVA10271
    UVA10739
    UVA10306
    节流防抖
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998650.html
Copyright © 2011-2022 走看看