CF1093G Multidimensional Queries(线段树)

思维题,对于曼哈顿距离,很多时候都是把绝对值拆开,我们发现,对于两个点一定是一正一负取大的,我们发现这就是对立的两种情况

进一步发现k只有5个,很容易联想到状压,因此我们对于最大的曼哈顿距离就是两个状态的和,他们的各个位仅有一个1并且总和有k个1

接下来我们只需要维护一个区间最大值,这可以使用线段树维护

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pll;
const int N=2e5+10;
const int inf=0x3f3f3f3f;
int n,k;
struct ele{
    int f[40];
};
struct node{
    int l,r;
    ele val;
}tr[N<<2];
int a[N][10];
void pushup(int u){
    for(int i=0;i<(1<<k);i++){
        tr[u].val.f[i]=max(tr[u<<1].val.f[i],tr[u<<1|1].val.f[i]);
    }
}
void build(int u,int l,int r){
    if(l==r){
        tr[u]={l,r};
        for(int i=0;i<(1<<k);i++){
            tr[u].val.f[i]=0;
            for(int j=0;j<k;j++){
                if(i>>j&1){
                    tr[u].val.f[i]+=a[l][j];
                }
                else{
                    tr[u].val.f[i]-=a[l][j];
                }
            }
        }
    }
    else{
        tr[u]={l,r};
        int mid=l+r>>1;
        build(u<<1,l,mid);
        build(u<<1|1,mid+1,r);
        pushup(u);
    }
}
void modify(int u,int x){
    if(tr[u].l==tr[u].r){
        for(int i=0;i<(1<<k);i++){
            tr[u].val.f[i]=0;
            for(int j=0;j<k;j++){
                if(i>>j&1){
                    tr[u].val.f[i]+=a[x][j];
                }
                else{
                    tr[u].val.f[i]-=a[x][j];
                }
            }
        }
        return ;
    }
    int mid=tr[u].l+tr[u].r>>1;
    if(x<=mid)
        modify(u<<1,x);
    else
        modify(u<<1|1,x);
    pushup(u);
}
ele merge(ele x,ele y){
    ele c;
    for(int i=0;i<(1<<k);i++){
        c.f[i]=max(x.f[i],y.f[i]);
    }
    return c;
}
ele query(int u,int l,int r){
    if(tr[u].l>=l&&tr[u].r<=r){
        return tr[u].val;
    }
    int mid=tr[u].l+tr[u].r>>1;
    if(l>mid)
        return query(u<<1|1,l,r);
    else if(r<=mid)
        return query(u<<1,l,r);
    else{
        auto d1=query(u<<1,l,r);
        auto d2=query(u<<1|1,l,r);
        d1=merge(d1,d2);
        return d1;
    }
}
int main(){
    ios::sync_with_stdio(false);
    cin>>n>>k;
    int i,j;
    for(i=1;i<=n;i++){
        for(j=0;j<k;j++){
            cin>>a[i][j];
        }
    }
    build(1,1,n);
    int q;
    cin>>q;
    while(q--){
        int opt;
        cin>>opt;
        if(opt==1){
            int x;
            cin>>x;
            for(i=0;i<k;i++){
                cin>>a[x][i];
            }
            modify(1,x);
        }
        else{
            int l,r;
            cin>>l>>r;
            auto tmp=query(1,l,r);
            int ans=0;
            for(i=0;i<(1<<k-1);i++){
                ans=max(ans,tmp.f[i]+tmp.f[(1<<k)-i-1]);
            }
            cout<<ans<<endl;
        }
    }
}
View Code

 

posted @ 2020-10-12 19:42  朝暮不思  阅读(108)  评论(0编辑  收藏  举报