[CF1093G]Multidimensional Queries
阿新 • • 發佈:2019-02-18
find 情況 線段樹 con 坐標 最小 \n void ==
[CF1093G]Multidimensional Queries
題目大意:
\(k(k\le5)\)維空間中有\(n(n\le2\times10^5)\)個點。\(m\)次操作,操作包含一下兩種:
- 將第\(i\)個點改為\((b_1,b_2,\ldots,b_k)\)。
- 詢問編號在\([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