• Gym


    题意:有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 }
  • 相关阅读:
    JVM 垃圾回收器工作原理及使用实例介绍(转载自IBM),直接复制粘贴,需要原文戳链接
    装tomcat和nginx心得
    jms的俩种模式
    裸奔Spring(1)
    一个最小mybatis
    SpringBoot和数据库连接
    SpringBoot的基础Pom
    SpringBoot读取配置文件
    埃拉托斯特尼素数筛法
    hdu 1175 连连看
  • 原文地址:https://www.cnblogs.com/asdfsag/p/11662618.html
Copyright © 2020-2023  润新知