對每列建區間線段樹直接肛過去
樹狀數組貌似比線段樹快很多
樹狀數組代碼(每行單獨維護):
#include<stdio.h>
#include<bits/stdc++.h>
#define ll long long
#define pii pair<int,int>
#define pll pair<ll,ll>
#define MEM(a,x) memset(a,x,sizeof(a))
#define lowbit(x) ((x)&-(x))
using namespace std;
const int inf=1e9+7;
const int N = 200 + 5;
struct Bit{
//a[i]=c1[1]+...+c1[i]
//c2[i]=i*c1[i]
//a[1]+...+a[i]=(i+1)*(c1[1]+...c[i])-(c2[1]+...+c2[i])
struct Bit2{
int n;
ll c[N];
void init(int n){
this->n=n;
fill(c,c+n+1,0);
}
void add(int x,ll val){
while(x<=n){
c[x]+=val;
x+=lowbit(x);
}
}
ll sum(int x){
ll ans=0;
while(x){
ans+=c[x];
x-=lowbit(x);
}
return ans;
}
}b1,b2;
void init(int n){
b1.init(n);
b2.init(n);
}
void add(int l,int r,ll x){//a[l...r]所有元素+x
b1.add(l,x);
b1.add(r+1,-x);
b2.add(l,l*x);
b2.add(r+1,-(r+1)*x);
}
ll query(int x){//查詢a[x]
return b1.sum(x);
}
ll querySum(int x){//查詢a[1]+...+a[x]
return b1.sum(x)*(x+1)-b2.sum(x);
}
}bit[N];
void slove(){
int x1,y1,x2,y2,z,a;
scanf("%d%d%d%d%d%d",&x1,&y1,&x2,&y2,&z,&a);
ll sum=0;
for(int i=y1;i<=y2;++i){
sum+=bit[i].querySum(x2)-bit[i].querySum(x1-1);
}
if(sum<(ll)z*(x2-x1+1)*(y2-y1+1)){
for(int i=y1;i<=y2;++i){
bit[i].add(x1,x2,a);
}
}
}
void print(int m,int n){
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
printf("%lld%c",bit[i].query(j),(j==m?'\n':' '));
}
}
}
int main(){
//freopen("/home/lu/code/r.txt","r",stdin);
//freopen("/home/lu/code/w.txt","w",stdout);
int m,n,q;
while(~scanf("%d%d%d",&m,&n,&q)){
for(int i=0;i<=n;++i){
bit[i].init(n);
}
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
int x;
scanf("%d",&x);
bit[i].add(j,j,x);
}
}
//print(m,n);
while(q--){
slove();
}
print(m,n);
}
return 0;
}
真※二維樹狀數組:
#include<stdio.h>
#include<bits/stdc++.h>
#define ll long long
#define pii pair<int,int>
#define pll pair<ll,ll>
#define MEM(a,x) memset(a,x,sizeof(a))
#define lowbit(x) ((x)&-(x))
using namespace std;
const int inf=1e9+7;
const int N = 200 + 5;
const int MAXN=N;
template<typename T>
class BIT{
struct BIT2{
int n,m;
T c[MAXN][MAXN];
void init(int n,int m){
this->n=n;
this->m=m;
for(int i=0;i<=n;++i){
fill(c[i],c[i]+m+1,0);
}
}
void add(int x,int y,T val){
for(int i=x; i<=n; i+=lowbit(i))
for(int j=y; j<=m; j+=lowbit(j))
c[i][j]+=val;
}
T sum(int x,int y){
T res=0;
for(int i=x; i; i-=lowbit(i))
for(int j=y; j; j-=lowbit(j))
res+=c[i][j];
return res;
}
} b[4];
void _add(int x,int y,T val){
b[0].add(x,y,val);
b[1].add(x,y,y*val);
b[2].add(x,y,x*val);
b[3].add(x,y,val*x*y);
}
T sum(int x,int y){
return b[0].sum(x,y)*(x+1)*(y+1)-(x+1)*b[1].sum(x,y)-(y+1)*b[2].sum(x,y)+b[3].sum(x,y);}
public:
void init(int n,int m){//初始化
for(int i=0;i<4;++i){
b[i].init(n,m);
}
}
void add(int l,int b,int r,int t,T val){//(l,b) (r,t)矩形內 所有元素+val
_add(l,b,val);
_add(l,t+1,-val);
_add(r+1,b,-val);
_add(r+1,t+1,val);
}
T query(int l,int b,int r,int t){//查詢(l,b) (r,t)矩形內 元素之和
return sum(r,t)-sum(l-1,t)-sum(r,b-1)+sum(l-1,b-1);
}
};
BIT<ll>bit;
void slove(){
int x1,y1,x2,y2,z,a;
scanf("%d%d%d%d%d%d",&x1,&y1,&x2,&y2,&z,&a);
ll sum=bit.query(y1,x1,y2,x2);
if(sum<(ll)z*(x2-x1+1)*(y2-y1+1)){
bit.add(y1,x1,y2,x2,a);
}
}
void print(int m,int n){
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
printf("%lld%c",bit.query(i,j,i,j),(j==m?'\n':' '));
}
}
}
int main(){
//freopen("/home/lu/code/r.txt","r",stdin);
//freopen("/home/lu/code/w.txt","w",stdout);
int m,n,q;
while(~scanf("%d%d%d",&m,&n,&q)){
bit.init(n,m);
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
int x;
scanf("%d",&x);
bit.add(i,j,i,j,x);
}
}
//print(m,n);
while(q--){
slove();
}
print(m,n);
}
return 0;
}
線段樹代碼:
#include<stdio.h>
#include<bits/stdc++.h>
#define ll long long
#define pii pair<int,int>
#define pll pair<ll,ll>
#define MEM(a,x) memset(a,x,sizeof(a))
#define lowbit(x) ((x)&-(x))
using namespace std;
const int inf=1e9+7;
const int N = 200;
struct RMQ{
ll rmqA[4*N],rmqB[4*N];
void init(){
MEM(rmqA,0);
MEM(rmqB,0);
}
void add(int k,int l,int r,int a,int b,int x){//[a,b]區間內所有元素+x
if(b<l||r<a){
return;
}
if(a<=l&&r<=b){
rmqA[k]+=x;
return;
}
if(l<r){
int mid=(l+r)/2;
add(2*k+1,l,mid,a,b,x);
add(2*k+2,mid+1,r,a,b,x);
rmqB[k]+=( min(r,b)-max(l,a) +1 ) * x;
}
}
ll query(int k,int l,int r,int a,int b){//查詢[a,b]區間和值
if(b<l||r<a){
return 0;
}
if(a<=l&&r<=b){
return rmqA[k]*(r-l+1)+rmqB[k];
}
ll ans=0;
if(l<r){
int mid=(l+r)/2;
ans+=query(2*k+1,l,mid,a,b);
ans+=query(2*k+2,mid+1,r,a,b);
}
return ans+( min(b,r)-max(a,l) +1 ) * rmqA[k];
}
}data[N];
void slove(int m){
int x1,y1,x2,y2,z,a;
scanf("%d%d%d%d%d%d",&x1,&y1,&x2,&y2,&z,&a);
ll sum=0;
for(int i=y1-1;i<y2;++i){//求矩陣的和
sum+=data[i].query(0,0,m-1,x1-1,x2-1);
}
if(sum<(ll)z*(x2-x1+1)*(y2-y1+1)){//均值是否<z
for(int i=y1-1;i<y2;++i){
data[i].add(0,0,m-1,x1-1,x2-1,a);
}
}
}
void print(int m,int n){
for(int i=0;i<m;++i){
for(int j=0;j<n;++j){
printf("%lld%c",data[i].query(0,0,n-1,j,j),(j==n-1?'\n':' '));
}
}
}
int main(){
//freopen("/home/lu/code/r.txt","r",stdin);
//freopen("/home/lu/code/w.txt","w",stdout);
int m,n,q;
while(~scanf("%d%d%d",&m,&n,&q)){
for(int i=0;i<n;++i){
data[i].init();
}
for(int i=0;i<n;++i){
for(int j=0;j<m;++j){
int x;
scanf("%d",&x);
data[i].add(0,0,m-1,j,j,x);
}
}
while(q--){
slove(n);
}
print(m,n);
}
return 0;
}