CodeForces - 1093G:Multidimensional Queries (线段树求K维最远点距离)

题意:给定N个K维的点,Q次操作,或者修改点的坐标;或者问[L,R]这些点中最远的点。

思路:因为最后一定可以表示维+/-(x1-x2)+/-(y1-y2)+/-(z1-z2).....

所以我们可以保存到线段树里,每次求区间最大值和最小值即可。

注意到我们可以先确定一个点的正负号,所以时间和空间节省了一半。

#include<bits/stdc++.h>
#define mp make_pair
#define pii pair<int,int>
#define F first
#define S second
#define lson Now<<1
#define rson Now<<1|1
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=800000;
const int inf=1000000000;
struct T
{
    int Mx[maxn],Mn[maxn];
    void update(int Now,int L,int R,int pos,int val)
    {
        if(L==R){ Mn[Now]=Mx[Now]=val; return ;}
        int Mid=(L+R)>>1;
        if(pos<=Mid) update(lson,L,Mid,pos,val);
        else update(rson,Mid+1,R,pos,val);
        Mx[Now]=max(Mx[lson],Mx[rson]); Mn[Now]=min(Mn[lson],Mn[rson]);
    }
    pii query(int Now,int L,int R,int l,int r)
    {
        if(l<=L&&r>=R) return mp(Mx[Now],Mn[Now]);
        int Mid=(L+R)>>1; int mx=-inf,mn=inf; pii tmp;
        if(l<=Mid){
            tmp=query(lson,L,Mid,l,r);
            mx=max(mx,tmp.F); mn=min(mn,tmp.S);
        }
        if(r>Mid){
            tmp=query(rson,Mid+1,R,l,r);
            mx=max(mx,tmp.F); mn=min(mn,tmp.S);
        }
        return mp(mx,mn);
    }
}t[16];
int main()
{
    int N,K,M,opt,L,R,p,x[6],KK;
    scanf("%d%d",&N,&K); KK=(1<<(K-1))-1;
    rep(i,0,KK){
        rep(j,0,N*4) t[i].Mn[j]=inf,t[i].Mx[j]=-inf;
    }
    rep(i,1,N){
        rep(j,0,K-1) scanf("%d",&x[j]);
        rep(j,0,KK) {
            int tmp=0;
            rep(k,0,K-1) if(j&(1<<k)) tmp+=x[k];else tmp-=x[k];
            t[j].update(1,1,N,i,tmp);
        }
    }
    scanf("%d",&M);
    rep(i,1,M){
        scanf("%d",&opt);
        if(opt==2){
            scanf("%d%d",&L,&R);
            int ans=-inf; pii tmp;
            rep(j,0,KK){
               pii tmp=t[j].query(1,1,N,L,R);
               ans=max(ans,tmp.F-tmp.S);
               ans=max(ans,tmp.S-tmp.F);
            }
            printf("%d\n",ans);
        }
        else {
            scanf("%d",&p); rep(j,0,K-1) scanf("%d",&x[j]);
            rep(j,0,KK) {
                int tmp=0;
                rep(k,0,K-1) if(j&(1<<k)) tmp+=x[k];else tmp-=x[k];
                t[j].update(1,1,N,p,tmp);
            }
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/hua-dong/p/10126497.html
今日推荐