1. 程式人生 > >[CF1093G]Multidimensional Queries

[CF1093G]Multidimensional Queries

find 情況 線段樹 con 坐標 最小 \n void ==

[CF1093G]Multidimensional Queries

題目大意:

\(k(k\le5)\)維空間中有\(n(n\le2\times10^5)\)個點。\(m\)次操作,操作包含一下兩種:

  1. 將第\(i\)個點改為\((b_1,b_2,\ldots,b_k)\)
  2. 詢問編號在\([l,r]\)內的所有點對中,曼哈頓距離的最大值。

思路:

枚舉每一維坐標對答案的貢獻的符號是正還是負,總共\(2^{k-1}\)種情況。每種情況用線段樹維護最大/最小值。詢問時在每棵線段樹上查詢區間最大值-區間最小值,對所有的情況取最大值即可。

時間復雜度\(\mathcal O(2^kn\log n)\)

源代碼:

#include<cstdio>
#include<cctype>
#include<climits>
#include<algorithm>
inline int getint() {
    register char ch;
    register bool neg=false;
    while(!isdigit(ch=getchar())) neg|=ch=='-';
    register int x=ch^'0';
    while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    return neg?-x:x;
}
const int N=2e5+1,K=5;
int n,k,a[K];
class SegmentTree {
    #define _left <<1
    #define _right <<1|1
    #define mid ((b+e)>>1)
    private:
        int max[N<<2],min[N<<2];
        void push_up(const int &p) {
            max[p]=std::max(max[p _left],max[p _right]);
            min[p]=std::min(min[p _left],min[p _right]);
        }
    public:
        void modify(int p,const int &y) {
            max[p]=min[p]=y;
            while(p!=1) {
                p>>=1;
                push_up(p);
            }
        }
        int qmax(const int &p,const int &b,const int &e,const int &l,const int &r) const {
            if(b==l&&e==r) return max[p];
            int ret=INT_MIN;
            if(l<=mid) ret=std::max(ret,qmax(p _left,b,mid,l,std::min(mid,r)));
            if(r>mid) ret=std::max(ret,qmax(p _right,mid+1,e,std::max(mid+1,l),r));
            return ret;
        }
        int qmin(const int &p,const int &b,const int &e,const int &l,const int &r) const {
            if(b==l&&e==r) return min[p];
            int ret=INT_MAX;
            if(l<=mid) ret=std::min(ret,qmin(p _left,b,mid,l,std::min(mid,r)));
            if(r>mid) ret=std::min(ret,qmin(p _right,mid+1,e,std::max(mid+1,l),r));
            return ret;
        }
    #undef _left
    #undef _right
    #undef mid
};
SegmentTree t[1<<K];
inline int query(const int &s,const int &l,const int &r) {
    return t[s].qmax(1,1,n,l,r)-t[s].qmin(1,1,n,l,r);
}
inline int find(const int &x) {
    int b=1,e=n,p=1;
    while(b<e) {
        const int mid=(b+e)>>1;
        if(x<=mid) {
            e=mid;
            p=p<<1;
        } else {
            b=mid+1;
            p=p<<1|1;
        }
    }
    return p;
}
int main() {
    n=getint(),k=getint();
    for(register int i=1;i<=n;i++) {
        for(register int i=0;i<k;i++) a[i]=getint();
        const int pos=find(i);
        for(register int s=0;s<1<<(k-1);s++) {
            int val=0;
            for(register int j=0;j<k;j++) {
                val+=a[j]*(s>>j&1?:-1);
            }
            t[s].modify(pos,val);
        }
    }
    const int q=getint();
    for(register int i=0;i<q;i++) {
        const int opt=getint();
        if(opt==1) {
            const int x=getint(),pos=find(x);
            for(register int i=0;i<k;i++) a[i]=getint();
            for(register int s=0;s<1<<(k-1);s++) {
                int val=0;
                for(register int j=0;j<k;j++) {
                    val+=a[j]*(s>>j&1?:-1);
                }
                t[s].modify(pos,val);
            }
        }
        if(opt==2) {
            const int l=getint(),r=getint();
            int ans=0;
            for(register int s=0;s<1<<(k-1);s++) {
                ans=std::max(ans,query(s,l,r));
            }
            printf("%d\n",ans);
        }
    }
    return 0;
}

[CF1093G]Multidimensional Queries