• 差分+树状数组【p4868】Preprefix sum


    Description

    前缀和(prefix sum)(S_i=sum_{k=1}^i a_i)

    前前缀和(preprefix sum) 则把(S_i)作为原序列再进行前缀和。记再次求得前缀和第i个是(SS_i)

    给一个长度n的序列(a_1, a_2, cdots, a_n)有两种操作:

    1. Modify i x:把(a_i)改成(x)
    2. Query i:查询(SS_i)

    Input

    第一行给出两个整数N,M。分别表示序列长度和操作个数

    接下来一行有N个数,即给定的序列a1,a2,....an

    接下来M行,每行对应一个操作,格式见题目描述

    Output

    对于每个询问操作,输出一行,表示所询问的SSi的值。

    显然,这是差分+树状数组

    题目中给定的(a_i)就是我们的差分数组。

    不会差分的小伙汁,来这里

    安利很好的写树状数组的博客.

    然后推一下式子.

    如果我们修改差分数组(a_i),显然,(S_i)会变化.

    (S_i=S_{i-1}+a_i)

    现在变成了

    (S_i=S_{i-1}+x)

    那么差值就变成了(x-a_i)

    那么,我们就(add(i,x-a[i])),不要忘了最后将(a_i)变为(x)

    代码

    #include<cstdio>
    #include<algorithm>
    #include<iostream>
    #define int long long
    #define R register
    using namespace std;
    inline void in(int &x)
    {
    	int f=1;x=0;char s=getchar();
    	while(!isdigit(s)){if(s=='-')f=-1;s=getchar();}
    	while(isdigit(s)){x=x*10+s-'0';s=getchar();}
    	x*=f;
    }
    int n,m,last,t1[1000008],t2[1000008],a[1000008];
    #define lowbit(x) x&-x
    inline void add(int pos,int x)
    {
    	for(R int i=pos;i<=n;i+=lowbit(i))
    		t1[i]+=x,t2[i]+=pos*x;
    }
    inline int query(int pos)
    {
    	R int res=0;
    	for(R int i=pos;i;i-=lowbit(i))
    		res+=t1[i]*(pos+1)-t2[i];
    	return res;
    }
    char opt[8];
    signed main()
    {
    	in(n),in(m);
    	for(R int i=1,x;i<=n;i++)
    	{
    		in(a[i]);
    		add(i,a[i]);
    	}
    	for(R int i=1,x,y;i<=m;i++)
    	{
    		scanf("%s",opt+1);
    		if(opt[1]=='Q')
    		{
    			in(x);
    			printf("%lld
    ",query(x));
    		}
    		else
    		{
    			in(x),in(y);
    			add(x,y-a[x]);
    			a[x]=y;
    		}
    	}
    }
    
  • 相关阅读:
    语法树,短语,直接短语,句柄2.0
    语法树,短语,直接短语,句柄
    2.理解文法和语文
    编译原理的学习 No.1
    第一次个人编程作业
    Arduboy基本操作(二)
    Arduboy基本用法(一)
    物理存储管理实训题
    创建和管理用户作业
    PL/SQL语言基础
  • 原文地址:https://www.cnblogs.com/-guz/p/9858504.html
Copyright © 2020-2023  润新知