C82 树状数组 区修+区查 P3372 线段树1

视频链接:C82 树状数组 区修+区查 Luogu P3372 线段树 1_哔哩哔哩_bilibili

 

 

Luogu P3372【模板】线段树 1

// 树状数组 区修+区查 O(nlogn)
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

const int N=100005;
typedef long long LL;
LL n,m,a[N],b[N];
//a:di的区间和, b:di*(i-1)的区间和

void add(LL*s,LL x,LL k){ //点修
  while(x<=n) s[x]+=k, x+=x&-x;
}
LL sum(LL*s,LL x){ //前缀和
  LL t=0;
  while(x) t+=s[x], x-=x&-x;
  return t;
}
int main(){
  scanf("%lld%lld",&n,&m); LL op,x,y,k;
  for(LL i=1;i<=n;i++){ //点修
    scanf("%lld",&k);
    add(a,i,k); add(a,i+1,-k);
    add(b,i,k*(i-1)); add(b,i+1,-k*i);
  }
  for(LL i=1;i<=m;i++){
    scanf("%lld%lld%lld",&op,&x,&y);
    if(op==1){ //区修
      scanf("%lld",&k);
      add(a,x,k); add(a,y+1,-k);
      add(b,x,k*(x-1)); add(b,y+1,-k*y);
    }
    else{ //区查
      k=(sum(a,y)*y-sum(b,y))
       -(sum(a,x-1)*(x-1)-sum(b,x-1));
      printf("%lld\n",k);
    }
  }
}

 

// 树状数组 区修+区查 O(nlogn)
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

const int N=100005;
typedef long long LL;
LL n,m;

struct BIT{ //树状数组
  LL s[N];
  void add(LL x,LL k){ //点修
    while(x<=n) s[x]+=k, x+=x&-x;
  }
  LL sum(LL x){ //前缀和
    LL t=0;
    while(x) t+=s[x], x-=x&-x;
    return t;
  }
}a,b; //a:di的区间和, b:di*(i-1)的区间和

int main(){
  scanf("%lld%lld",&n,&m); LL op,x,y,k;
  for(LL i=1;i<=n;i++){ //点修
    scanf("%lld",&k);
    a.add(i,k); a.add(i+1,-k);
    b.add(i,k*(i-1)); b.add(i+1,-k*i);
  }
  for(LL i=1;i<=m;i++){
    scanf("%lld%lld%lld",&op,&x,&y);
    if(op==1){ //区修
      scanf("%lld",&k);
      a.add(x,k); a.add(y+1,-k);
      b.add(x,k*(x-1)); b.add(y+1,-k*y);
    }
    else{ //区查
      k=(a.sum(y)*y-b.sum(y))
       -(a.sum(x-1)*(x-1)-b.sum(x-1));
      printf("%lld\n",k);
    }
  }
}

 

posted @ 2023-12-29 10:14  董晓  阅读(331)  评论(0编辑  收藏  举报