1. 程式人生 > >CodeForces - 1093G:Multidimensional Queries (線段樹求K維最遠點距離)

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; }