[CF1093G]Multidimensional Queries:线段树
分析
非常有趣的一道题。
式子中的绝对值很难处理,但是我们发现:
\[\sum_{i=1}^{k}|a_{x,i}-a_{y,i}|=\sum_{i=1}^{k}max(a_{x,i}-a_{y,i},a_{y,i}-a_{x,i})=max\{\sum_{i=1}^{k}c_ia_{x,i}-\sum_{i=1}^{k}c_ia_{y,i}\}
\]
其中\(c\)是所有长度为\(k\)的只由\(-1\)和\(1\)组成的数列,共有\(2^k\)种。
所以我们可以对于每一种\(c\)维护一棵支持单点修改,查询区间最小值和最大值的线段树,对所有的极差取\(max\)即可。
代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cctype>
#include <algorithm>
#define rin(i,a,b) for(int i=(a);i<=(b);i++)
#define rec(i,a,b) for(int i=(a);i>=(b);i--)
#define trav(i,a) for(int i=head[(a)];i;i=e[i].nxt)
typedef long long LL;
using std::cin;
using std::cout;
using std::endl;
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x*f;
}
const int MAXN=200005;
int n,k,q,cnt,loc,ql,qr,xx[MAXN][6];
struct sgt{
int maxn[33],minn[33];
}a[MAXN<<2],kk;
#define mid ((l+r)>>1)
#define lc (o<<1)
#define rc ((o<<1)|1)
inline sgt mer(sgt x,sgt y){
rin(i,0,cnt-1) x.maxn[i]=std::max(x.maxn[i],y.maxn[i]),x.minn[i]=std::min(x.minn[i],y.minn[i]);
return x;
}
void build(int o,int l,int r){
if(l==r){
rin(i,0,cnt-1){
rin(j,0,k-1){
if((i>>j)&1) a[o].maxn[i]+=xx[l][j];
else a[o].maxn[i]-=xx[l][j];
}
a[o].minn[i]=a[o].maxn[i];
}
return;
}
build(lc,l,mid);build(rc,mid+1,r);
a[o]=mer(a[lc],a[rc]);
}
void upd(int o,int l,int r){
if(l==r){
a[o]=kk;
return;
}
if(loc<=mid) upd(lc,l,mid);
else upd(rc,mid+1,r);
a[o]=mer(a[lc],a[rc]);
}
sgt query(int o,int l,int r){
if(ql<=l&&r<=qr) return a[o];
if(mid<ql) return query(rc,mid+1,r);
else if(mid>=qr) return query(lc,l,mid);
else return mer(query(lc,l,mid),query(rc,mid+1,r));
}
#undef mid
#undef lc
#undef rc
int main(){
n=read(),k=read();cnt=(1<<k);
rin(i,1,n) rin(j,0,k-1) xx[i][j]=read();
build(1,1,n);
q=read();
while(q--){
int opt=read();
if(opt==1){
loc=read();rin(i,0,k-1) xx[0][i]=read();
rin(i,0,cnt-1){
kk.maxn[i]=0;
rin(j,0,k-1){
if((i>>j)&1) kk.maxn[i]+=xx[0][j];
else kk.maxn[i]-=xx[0][j];
}
kk.minn[i]=kk.maxn[i];
}
upd(1,1,n);
}
else{
ql=read(),qr=read();
sgt Ans=query(1,1,n);int ans=0;
rin(i,0,cnt-1) ans=std::max(ans,Ans.maxn[i]-Ans.minn[i]);
printf("%d\n",ans);
}
}
return 0;
}
posted on 2018-12-20 19:43 ErkkiErkko 阅读(295) 评论(2) 编辑 收藏 举报