zoukankan      html  css  js  c++  java
  • bzoj 3155: Preprefix sum

    树状数组

    我们需要求的是(displaystyle sum_{i=1}^{k}S_i) ,即(displaystyle sum_{i=1}^{k}sum_{j=1}^{i}a_j).

    暴力求解肯定是不行的,化简式子是OIer的优良传统,所以我们可以考虑化简一下式子。

    我们可以考虑一下每一个元素对前前缀合的贡献,第(i)个数被(i)~(k)之间的每一个(S_j)都计算了一遍,所以它的贡献就是(displaystyle (k-i+1) imes a_i),我们需要求的就是(displaystyle sum_{i=1}^{k}(k-i+1) imes a_i)

    我们回到单个元素,根据乘法分配率,我们就得到((k-i+1) imes a_i=(k+1) imes a_i-i imes a_i),

    所以(displaystyle sum_{i=1}^{k}(k-i+1) imes a_i=sum_{i=1}^{k}(k+1) imes a_i-sum_{i=1}^{k}i imes a_i)

    再将((k+1))提出来之后就得到式子(displaystyle (k+1)sum_{i=1}^{k} a_i-sum_{i=1}^{k}i imes a_i)

    对于(displaystyle sum_{i=1}^{k} a_i)(displaystyle sum_{i=1}^{k}i imes a_i)我们都能够用树状数组来维护,这样我们就能快速的求出答案啦^_^。

    再考虑修改,只用这样写

    add1(x,y-a[x]);add2(x,(y-a[x])*x);
    

    就可以啦~,还是比较简单的。

    最后献上我丑陋的代码

    #include<algorithm>
    #include<iostream>
    #include<cstdio>
    #define int long long
    using namespace std;
    int n,m,x,y;
    const int N=100010;
    int ans,len;
    int a[N],tr1[N<<1],tr2[N<<1];
    char s[101];
    int read()
    {
    	char ch;int x=0,f=1;
    	while(!isdigit(ch=getchar()))
    	{(ch=='-')&&(f=-f);}
    	while(isdigit(ch))
    	{x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
        return x*f;
    }
    int lowbit(int x){return x&(-x);}
    void add1(int pos,int x)
    {
    	for(int i=pos;i<=(N<<1);i+=lowbit(i))tr1[i]+=x;
    }
    void add2(int pos,int x)
    {
    	for(int i=pos;i<=(N<<1);i+=lowbit(i))tr2[i]+=x;
    }
    int ask1(int pos)
    {
    	int lin=0;
    	for(int i=pos;i;i-=lowbit(i))lin+=tr1[i];
    	return lin;
    }
    int ask2(int pos)
    {
    	int lin=0;
    	for(int i=pos;i;i-=lowbit(i))lin+=tr2[i];
    	return lin;
    }
    signed main()
    {
    	cin>>n>>m;
    	for(int i=1;i<=n;++i)
    	{
    		a[i]=read();
    		add1(i,a[i]);add2(i,a[i]*i);
    	}
    	while(m--)
    	{
    		scanf("%s",s+1);
    		if(s[1]=='Q')
    		{
    			x=read();
    			ans=((x+1)*ask1(x)-ask2(x));
    			printf("%lld
    ",ans);
    		}
    		else
    		{
    			x=read();y=read();
    			add1(x,y-a[x]);add2(x,(y-a[x])*x);
    			a[x]=y;
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    (并查集)小希的迷宫 --HDU -- 1272
    (并查集)Connections in Galaxy War -- zoj --3261 还没写
    (并查集)A Bug's Life -- POJ -- 2492
    LINQ 图解 LINQ学习第三篇 [转]
    C# 4.0 新特性-dynamic 【转】
    C#编程规范
    C#中关于DateTime的最大值和最小值
    .NET,你忘记了么?(八)—— 从dynamic到特性误用 [转]
    C#中dynamic的正确用法【转】
    ASP.NET MVC 中将FormCollection与实体间转换方法【转】
  • 原文地址:https://www.cnblogs.com/wljss/p/11505396.html
Copyright © 2011-2022 走看看