2018 shenyang ICPC E - The Kouga Ninja Scrolls

 维护区间最大值,区间最小值。区间次小值,区间次大值。且区间最大值和次大值,最小值和次小值不能同色。

注意转换为切比雪夫距离之后,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;
    }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值