[CF1093G]Multidimensional Queries:线段树

分析

非常有趣的一道题。

式子中的绝对值很难处理,但是我们发现:

\[\sum_{i=1}^{k}|a_{x,i}-a_{y,i}|=\sum_{i=1}^{k}max(a_{x,i}-a_{y,i},a_{y,i}-a_{x,i})=max\{\sum_{i=1}^{k}c_ia_{x,i}-\sum_{i=1}^{k}c_ia_{y,i}\}\]

其中\(c\)是所有长度为\(k\)的只由\(-1\)\(1\)组成的数列,共有\(2^k\)种。

所以我们可以对于每一种\(c\)维护一棵支持单点修改,查询区间最小值和最大值的线段树,对所有的极差取\(max\)即可。

代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cctype>
#include <algorithm>
#define rin(i,a,b) for(int i=(a);i<=(b);i++)
#define rec(i,a,b) for(int i=(a);i>=(b);i--)
#define trav(i,a) for(int i=head[(a)];i;i=e[i].nxt)
typedef long long LL;
using std::cin;
using std::cout;
using std::endl;

inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    return x*f;
}

const int MAXN=200005;
int n,k,q,cnt,loc,ql,qr,xx[MAXN][6];
struct sgt{
    int maxn[33],minn[33];
}a[MAXN<<2],kk;

#define mid ((l+r)>>1)
#define lc (o<<1)
#define rc ((o<<1)|1)
inline sgt mer(sgt x,sgt y){
    rin(i,0,cnt-1) x.maxn[i]=std::max(x.maxn[i],y.maxn[i]),x.minn[i]=std::min(x.minn[i],y.minn[i]);
    return x;
}

void build(int o,int l,int r){
    if(l==r){
        rin(i,0,cnt-1){
            rin(j,0,k-1){
                if((i>>j)&1) a[o].maxn[i]+=xx[l][j];
                else a[o].maxn[i]-=xx[l][j];
            }
            a[o].minn[i]=a[o].maxn[i];
        }
        return;
    }
    build(lc,l,mid);build(rc,mid+1,r);
    a[o]=mer(a[lc],a[rc]);
}

void upd(int o,int l,int r){
    if(l==r){
        a[o]=kk;
        return;
    }
    if(loc<=mid) upd(lc,l,mid);
    else upd(rc,mid+1,r);
    a[o]=mer(a[lc],a[rc]);
}

sgt query(int o,int l,int r){
    if(ql<=l&&r<=qr) return a[o];
    if(mid<ql) return query(rc,mid+1,r);
    else if(mid>=qr) return query(lc,l,mid);
    else return mer(query(lc,l,mid),query(rc,mid+1,r));
}
#undef mid
#undef lc
#undef rc

int main(){
    n=read(),k=read();cnt=(1<<k);
    rin(i,1,n) rin(j,0,k-1) xx[i][j]=read();
    build(1,1,n);
    q=read();
    while(q--){
        int opt=read();
        if(opt==1){
            loc=read();rin(i,0,k-1) xx[0][i]=read();
            rin(i,0,cnt-1){
                kk.maxn[i]=0;
                rin(j,0,k-1){
                    if((i>>j)&1) kk.maxn[i]+=xx[0][j];
                    else kk.maxn[i]-=xx[0][j];
                }
                kk.minn[i]=kk.maxn[i];
            }
            upd(1,1,n);
        }
        else{
            ql=read(),qr=read();
            sgt Ans=query(1,1,n);int ans=0;
            rin(i,0,cnt-1) ans=std::max(ans,Ans.maxn[i]-Ans.minn[i]);
            printf("%d\n",ans);
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/ErkkiErkko/p/10151832.html