[CF1093G]Multidimensional Queries

[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;
}
posted @ 2019-02-18 19:03  skylee03  阅读(195)  评论(0编辑  收藏  举报