• [bzoj 3155] Preprefix sum


    [bzoj 3155] Preprefix sum

    Description

    Input

    第一行给出两个整数N,M。分别表示序列长度和操作个数
    接下来一行有N个数,即给定的序列a1,a2,….an
    接下来M行,每行对应一个操作,格式见题目描述

    Output

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

    Sample Input

    5 3 
    1 2 3 4 5 
    Query 5 
    Modify 3 2 
    Query 5 
    

    Sample Output

    35 
    32 
    

    HINT

    1<=N,M<=100000,且在任意时刻0<=Ai<=100000

    唉,这题可以维护系数做,也可以直接用线段数搞.这里我用简单的方法,直接搞!我们直接维护sum[i]的值,那么询问pos相当于区间([1,pos])的sum和.修改A[i]也好办,区间修改i~n的sum值就行了,改成加法的操作,就可以上线段树.不过也可以用拆一下SSi来用树状数组维护一下系数.有点麻烦,我不讲了.但是这里我用树状数组代替了线段树执行区间修改和区间查询的操作,至于这个是怎么来的,其实也有点像之前那个维护系数的方法,用差分的思路去做就好了.

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    typedef long long LL;
    
    static const int maxm = 1e5 + 10;
    
    LL tr1[maxm],tr2[maxm],A[maxm],sum[maxm];
    char ch[10];
    int n,m,pos;
    
    int lowbit(int x){
    	return x&-x;
    }
    
    void Upt(int k,LL val){
    	for(int i = k; i <= n ;i += lowbit(i))
    		tr1[i] += val,tr2[i] += 1LL * k * val;
    }
    
    LL Query(int k){
    	LL ret = 0;
    	for(int i = k ; i ;i -= lowbit(i))
    		ret += 1LL * (k+1) * tr1[i] - tr2[i];
    	return ret;
    }
    
    int main(){
    	LL x;
    	scanf("%d%d",&n,&m);
    	for(int i = 1;i <= n ;i++)
    		scanf("%lld",&A[i]),sum[i]=sum[i-1]+A[i];
    	
    	for(int i = 1;i <= n ;i++)
    		Upt(i,sum[i]),Upt(i+1,-sum[i]);
    	
    	while(m--){
    		scanf("%s",ch);	
    		if(ch[0]=='M'){
    			scanf("%d%lld",&pos,&x);
    			Upt(pos,x-A[pos]);Upt(n+1,A[pos]-x);
    			A[pos]=x;
    		}else{
    			scanf("%d",&pos);
    			printf("%lld
    ",Query(pos));
    		}
    	}
    
    	return 0;
    }
    

    传送门

  • 相关阅读:
    类加载器
    hibernate笔记
    windows笔记
    maven笔记
    mysql笔记
    jsonp使用
    [ZJU 1010] Area
    [ZJU 1004] Anagrams by Stack
    [ZJU 1003] Crashing Balloon
    [ZJU 1002] Fire Net
  • 原文地址:https://www.cnblogs.com/Exbilar/p/6869694.html
Copyright © 2020-2023  润新知