维护区间最大值,区间最小值。区间次小值,区间次大值。且区间最大值和次大值,最小值和次小值不能同色。
注意转换为切比雪夫距离之后,x和y的值可以分开来考虑。不过维护的时候别重新写两个函数维护,这样太丑了。
还有一个小trick是查询时 ,不需要上传合并,直接与答案一起push_up就好了。这里合并一次的复杂度太高了。
#include <bits/stdc++.h>
#define lc l,mid,x<<1
#define rc mid+1,r,x<<1|1LL
using namespace std;
typedef long long LL;
typedef LL lint;
const lint maxn = 100005;
const lint inf = 0x3f3f3f3f3f3f;
struct Point{
lint x,y,c;
Point( lint xx=0,lint yy=0,lint cc = 0 ){
x=xx;y=yy;c = cc;
}
}a[maxn];
struct node {
lint val[2][5], color[2][5];
node(){
for( lint i = 0;i < 2;i++ ) {
val[i][1] = inf;
color[i][1] = 0;
val[i][2] = inf;
color[i][1] = 0;
val[i][3] = -inf;
color[i][3] = 0;
val[i][4] = -inf;
color[i][4] = 0;
}
}
}tree[4*maxn];
node up( const node& a,const node& b ){
node res;
for( lint i = 0;i< 2;i++ ) {
res.val[i][1] = min(a.val[i][1], b.val[i][1]);
res.color[i][1] = (a.val[i][1] < b.val[i][1]) ? a.color[i][1] : b.color[i][1];
res.val[i][4] = max(a.val[i][4], b.val[i][4]);
res.color[i][4] = (a.val[i][4] > b.val[i][4]) ? a.color[i][4] : b.color[i][4];
if (a.color[i][1] != b.color[i][1]) {
res.val[i][2] = max(a.val[i][1], b.val[i][1]);
res.color[i][2] = (a.val[i][1] > b.val[i][1]) ? a.color[i][1] : b.color[i][1];
}
if (a.color[i][4] != b.color[i][4]) {
res.val[i][3] = min(a.val[i][4], b.val[i][4]);
res.color[i][3] = (a.val[i][4] < b.val[i][4]) ? a.color[i][4] : b.color[i][4];
}
if (a.val[i][2] < res.val[i][2] && a.color[i][2] != res.color[i][1]) {
res.val[i][2] = a.val[i][2];
res.color[i][2] = a.color[i][2];
}
if (b.val[i][2] < res.val[i][2] && b.color[i][2] != res.color[i][1]) {
res.val[i][2] = b.val[i][2];
res.color[i][2] = b.color[i][2];
}
if (a.val[i][3] > res.val[i][3] && a.color[i][3] != res.color[i][4]) {
res.val[i][3] = a.val[i][3];
res.color[i][3] = a.color[i][3];
}
if (b.val[i][3] > res.val[i][3] && b.color[i][3] != res.color[i][4]) {
res.val[i][3] = b.val[i][3];
res.color[i][3] = b.color[i][3];
}
}
return res;
}
void push_up( lint x ){
tree[x]=up( tree[x<<1LL],tree[x<<1|1LL] );
}
void update( lint left,lint right,lint x0,lint y0,lint c,lint l,lint r,lint x ){
if( left <= l && right >=r ){
tree[x].val[0][1]=x0; tree[x].color[0][1]=c;
tree[x].val[0][2]=inf; tree[x].color[0][2]=0;
tree[x].val[0][3]=-inf; tree[x].color[0][3]=0;
tree[x].val[0][4]=x0; tree[x].color[0][4]=c;
tree[x].val[1][1]=y0; tree[x].color[1][1]=c;
tree[x].val[1][2]=inf; tree[x].color[1][2]=0;
tree[x].val[1][3]=-inf; tree[x].color[1][3]=0;
tree[x].val[1][4]=y0; tree[x].color[1][4]=c;
return;
}
lint mid = l+r>>1;
if( left <= mid) update( left,right,x0,y0,c,lc );
if(right > mid) update(left,right,x0,y0,c,rc);
push_up(x);
}
node res;
void query( lint left,lint right,lint l,lint r,lint x ){
if( left <= l && right >=r ){
res = up( res,tree[x] );
return;
}
lint mid = l + r >>1 ;
if( left <= mid ) query( left,right,lc );
if( right>mid ) query(left,right,rc);
}
LL solve( node x ){
LL res = 0;
for( lint i = 0;i < 2;i++ ){
if( x.color[i][1] != x.color[i][4] && x.color[i][1] && x.color[i][4] ){
res = max( res,(LL)x.val[i][4]-x.val[i][1] );
}
if( x.color[i][3]!=x.color[i][1] && x.color[i][3] && x.color[i][1] ){
res=max( res,(LL)x.val[i][3]-x.val[i][1] );
}
if( x.color[i][2]!=x.color[i][4] && x.color[i][2] && x.color[i][4] ){
res=max(res,(LL)x.val[i][4]-x.val[i][2]);
}
}
return res;
}
void build( lint l,lint r,lint x ){
if( l == r ){
tree[x].val[0][1]=a[l].x; tree[x].color[0][1]=a[l].c;
tree[x].val[0][2]=inf; tree[x].color[0][2]=0;
tree[x].val[0][3]=-inf; tree[x].color[0][3]=0;
tree[x].val[0][4]=a[l].x; tree[x].color[0][4]=a[l].c;
tree[x].val[1][1]=a[l].y; tree[x].color[1][1]=a[l].c;
tree[x].val[1][2]=inf; tree[x].color[1][2]=0;
tree[x].val[1][3]=-inf; tree[x].color[1][3]=0;
tree[x].val[1][4]=a[l].y; tree[x].color[1][4]=a[l].c;
return;
}
lint mid = l+r >>1;
build( lc );
build( rc );
push_up(x);
}
int main(){
lint T,n,m,x,y,op,k,c,ca = 0;
scanf("%I64d",&T);
while(T--){
printf("Case #%I64d:\n",++ca);
scanf("%I64d%I64d",&n,&m);
for( lint i = 1;i <= n;i++ ){
scanf("%I64d%I64d%I64d",&x,&y,&c);
a[i]=Point(x+y,x-y,c);
}
build( 1,n,1 );
for(lint i=1;i<=m;i++){
scanf("%I64d",&op);
if(op==1){
scanf("%I64d%I64d%I64d",&k,&x,&y);
a[k].x+=x+y;a[k].y +=x-y;
update(k,k,a[k].x,a[k].y,a[k].c,1,n,1);
}else if(op==2){
scanf("%I64d%I64d",&k,&c);
a[k].c=c;
update( k,k,a[k].x,a[k].y,a[k].c,1,n,1 );
}else{
lint l,r;
scanf("%I64d%I64d",&l,&r);
node res2; res = res2;
query( l,r,1,n,1 );
LL ans = solve(res);
cout << ans << endl;
}
}
}
return 0;
}