• 2018网络预选赛 徐州H 线段树+树状数组


    设读入的数组是a,树状数组用来维护a数组区间和sum,线段树用来维护一个另一个数组ssum的区间和,区间每个点a[i]*(n-i+1),那么l-r的答案是l-r的ssum-(n-r)*(sum[r]-sum[l-1]) (纸上画一下就知道了)

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=100010;
    int n,q,ql,qr,p;
    long long v,_sum;
    long long sum[maxn],ssum[4*maxn],addv[4*maxn],c[maxn];
    long long ask(int x){
    	long long ans=0;
    	for(;x;x-=x&-x)ans+=sum[x];
    	return ans;
    }
    int add(int x,int y){
    	for(;x<=n;x+=x&-x)sum[x]+=y;
    }
    void update(int o,int L,int R){
    	if(L==R){
    		ssum[o]=v*(n-L+1);
    		return;
    	}
    	int M=L+(R-L)/2;
    	if(p<=M)update(o*2,L,M);
    	else update(o*2+1,M+1,R);
    	ssum[o]=ssum[o*2]+ssum[o*2+1];
    }
    long long query(int o,int L,int R){
    	int M=L+(R-L)/2;
    	long long ans=0;
    	if(ql<=L&&R<=qr)return ssum[o];
    	if(ql<=M)ans+=query(o*2,L,M);
    	if(M<qr)ans+=query(o*2+1,M+1,R);
    	return ans;
    }
    int main(){
    	int flag,a,b;
    	scanf("%d%d",&n,&q);
    	for(int i=1;i<=n;i++){
    		scanf("%lld",&c[i]);
    		add(i,c[i]);
    	}
    	for(int i=n;i>=1;i--){
    		p=i;
    		v=c[i];
    		update(1,1,n);
    	}
    	while(q--){
    		scanf("%d%d%d",&flag,&a,&b);
    		if(flag==1){
    			ql=a,qr=b;
    			_sum=query(1,1,n);
    			printf("%lld
    ",_sum-(n-b)*(ask(b)-ask(a-1)));
    		}
    		else{
    			add(a,b-c[a]);
    			ql=a,qr=n;
    			p=a,v=b;
    			update(1,1,n);
    			c[a]=b;
    		}
    	}
    }
    

      

  • 相关阅读:
    php生成二维码遇到的问题
    ua判断页面在什么终端/系统打开
    js实现复制文字到剪切板
    jquery 实现表单数据转化为对象格式
    [转]关于setTimeout()你所不知道的地方
    关于性能优化
    关于event loop
    JS数据结构与算法--双向链表
    JS数据结构与算法--单向链表
    JS数组去重
  • 原文地址:https://www.cnblogs.com/pkgunboat/p/9614926.html
Copyright © 2020-2023  润新知