51NOD 1210 矩陣查詢 【線段樹/樹狀數組】

傳送門


對每列建區間線段樹直接肛過去
樹狀數組貌似比線段樹快很多

樹狀數組代碼(每行單獨維護):

#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;
}
發佈了292 篇原創文章 · 獲贊 82 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章