[CF1093G]Multidimensional Queries:線段樹
阿新 • • 發佈:2018-12-20
分析
非常有趣的一道題。
式子中的絕對值很難處理,但是我們發現:
\[\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; }