C94 二维树状数组+差分 P4514 上帝造题的七分钟

视频链接:C94 二维树状数组+差分 P4514 上帝造题的七分钟_哔哩哔哩_bilibili

 

 

 

Luogu P4514 上帝造题的七分钟

// 二维树状数组+差分 区修+区查 O(q*logn*logn)
#include <cstdio>
using namespace std;

#define lowb(x) x&-x
int n,m,a,b,c,d,v; char op[2];
struct Tree{ //二维树状数组
  int s[2050][2050];
  void change(int x,int y,int v){ //向后修
    for(int i=x;i<=n;i+=lowb(i))
      for(int j=y;j<=m;j+=lowb(j))
        s[i][j]+=v;
  }
  int query(int x,int y){ //向前查
    int t=0;
    for(int i=x;i;i-=lowb(i))
      for(int j=y;j;j-=lowb(j))
        t+=s[i][j];
    return t;
  }
}A,B,C,D; //维护 d,d*i,d*j,d*i*j

void add(int x,int y,int v){ //点加
  A.change(x,y,v);
  B.change(x,y,v*x);
  C.change(x,y,v*y);
  D.change(x,y,v*x*y);
}
int sum(int x,int y){ //前缀和
  return A.query(x,y)*(x*y+x+y+1)
        -B.query(x,y)*(y+1)
        -C.query(x,y)*(x+1)
        +D.query(x,y);
}
int main(){
  scanf("X%d%d",&n,&m);
  while(~scanf("%s",&op)){
    scanf("%d%d%d%d",&a,&b,&c,&d);
    if(op[0]=='L'){ //区修变差分
      scanf("%d",&v);
      add(a,b,v);
      add(a,d+1,-v);
      add(c+1,b,-v);
      add(c+1,d+1,v);
    }
    else           //区间和
      printf("%d\n",sum(c,d)
      -sum(a-1,d)-sum(c,b-1)
      +sum(a-1,b-1));
  }
}

 

// 二维树状数组+差分 区修+区查 O(q*logn*logn)
#include <cstdio>
using namespace std;

#define lowb(x) x&-x
int n,m,a,b,c,d,v; char op[2];
int s[2050][2050][4];

void change(int x,int y,int k,int v){ //向后修
  for(int i=x;i<=n;i+=lowb(i))
    for(int j=y;j<=m;j+=lowb(j))
      s[i][j][k]+=v;
}
int query(int x,int y,int k){ //向前查
  int t=0;
  for(int i=x;i;i-=lowb(i))
    for(int j=y;j;j-=lowb(j))
      t+=s[i][j][k];
  return t;
}
void add(int x,int y,int v){ //点加
  change(x,y,0,v);
  change(x,y,1,v*x);
  change(x,y,2,v*y);
  change(x,y,3,v*x*y);
}
int sum(int x,int y){ //前缀和
  return query(x,y,0)*(x*y+x+y+1)
        -query(x,y,1)*(y+1)
        -query(x,y,2)*(x+1)
        +query(x,y,3);
}
int main(){
  scanf("X%d%d",&n,&m);
  while(~scanf("%s",&op)){
    scanf("%d%d%d%d",&a,&b,&c,&d);
    if(op[0]=='L'){ //区修变差分
      scanf("%d",&v);
      add(a,b,v);
      add(a,d+1,-v);
      add(c+1,b,-v);
      add(c+1,d+1,v);
    }
    else           //区间和
      printf("%d\n",sum(c,d)
      -sum(a-1,d)-sum(c,b-1)
      +sum(a-1,b-1));
  }
}

 

posted @ 2024-01-16 21:15  董晓  阅读(147)  评论(0编辑  收藏  举报