题意:有n个忍者(编号为1-n),每个忍者有三个属性:横坐标x,纵坐标y,所属门派c,要求支持三种操作:
1.改变第k个忍者的位置
2.改变第k个忍者的门派
3.查询编号为[l,r]之间的忍者中,所属门派不同的两个忍者的最大曼哈顿距离
通过曼哈顿距离变换,将每个忍者的横坐标和纵坐标拆成x+y和x-y,两种情况分别用线段树维护区间最大值,最小值,最大值和最小值所属门派,以及门派不同的次大值及次小值(非严格),查询时分两种情况:
1.最大值和最小值门派不同:答案为最大值-最小值
2.最大值和最小值门派相同:答案为max(最大值-次小值,次大值-最小值)
两种情况分别讨论一下,然后取个最大值即可。
无解的情况需要特判一下
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const ll N=1e5+10,inf=0x3f3f3f3f3f3f3f3fll; 5 ll n,m,X[N],Y[N],C[N],ka; 6 struct D {ll mx,smx,mi,smi,umx,umi;} tr[N<<2][2]; 7 D operator+(const D& a,const D& b) { 8 if(a.mx==~inf)return b; 9 if(b.mx==~inf)return a; 10 D c; 11 c.mx=max(a.mx,b.mx); 12 c.mi=min(a.mi,b.mi); 13 c.umx=c.mx==a.mx?a.umx:b.umx; 14 c.smx=max(a.smx,b.smx); 15 if(a.umx!=b.umx)c.smx=max(c.smx,min(a.mx,b.mx)); 16 c.umi=c.mi==a.mi?a.umi:b.umi; 17 c.smi=min(a.smi,b.smi); 18 if(a.umi!=b.umi)c.smi=min(c.smi,max(a.mi,b.mi)); 19 return c; 20 } 21 #define ls (u<<1) 22 #define rs (u<<1|1) 23 #define mid ((l+r)>>1) 24 void pu(ll u) {tr[u][0]=tr[ls][0]+tr[rs][0],tr[u][1]=tr[ls][1]+tr[rs][1];} 25 void build(ll u=1,ll l=1,ll r=n) { 26 if(l==r) { 27 tr[u][0]= {X[l]+Y[l],~inf,X[l]+Y[l],inf,C[l],C[l]}; 28 tr[u][1]= {X[l]-Y[l],~inf,X[l]-Y[l],inf,C[l],C[l]}; 29 return; 30 } 31 build(ls,l,mid),build(rs,mid+1,r),pu(u); 32 } 33 void upd(ll p,ll x,ll y,ll c,ll u=1,ll l=1,ll r=n) { 34 if(l==r) { 35 tr[u][0]= {x+y,~inf,x+y,inf,c,c}; 36 tr[u][1]= {x-y,~inf,x-y,inf,c,c}; 37 return; 38 } 39 p<=mid?upd(p,x,y,c,ls,l,mid):upd(p,x,y,c,rs,mid+1,r); 40 pu(u); 41 } 42 D qry(ll L,ll R,ll f,ll u=1,ll l=1,ll r=n) { 43 if(l>=L&&r<=R)return tr[u][f]; 44 if(l>R||r<L)return {~inf}; 45 return qry(L,R,f,ls,l,mid)+qry(L,R,f,rs,mid+1,r); 46 } 47 int main() { 48 ll T; 49 for(scanf("%lld",&T); T--;) { 50 printf("Case #%lld: ",++ka); 51 scanf("%lld%lld",&n,&m); 52 for(ll i=1; i<=n; ++i)scanf("%lld%lld%lld",&X[i],&Y[i],&C[i]); 53 build(); 54 while(m--) { 55 ll f,l,r,k,c,x,y; 56 scanf("%lld",&f); 57 if(f==1)scanf("%lld%lld%lld",&k,&x,&y),upd(k,X[k]+=x,Y[k]+=y,C[k]); 58 else if(f==2)scanf("%lld%lld",&k,&c),upd(k,X[k],Y[k],C[k]=c); 59 else if(f==3) { 60 scanf("%lld%lld",&l,&r); 61 D a=qry(l,r,0),b=qry(l,r,1); 62 ll x=a.umx==a.umi?max(a.mx-a.smi,a.smx-a.mi):a.mx-a.mi; 63 ll y=b.umx==b.umi?max(b.mx-b.smi,b.smx-b.mi):b.mx-b.mi; 64 printf("%lld ",a.smx==~inf?0:max(x,y)); 65 } 66 } 67 } 68 return 0; 69 }