zoukankan      html  css  js  c++  java
  • 【xsy1144】选物品 主席树

    题目大意:$N$ 件物品摆成一排,给每个物品定义两个属性 $A$ 和$ B$,两件物品的 差异度 定义为它们两种属性的差的绝对值中较大的一个。如果要求出一些物品的差异度,我们先定义一个 理想物品,使它与这些物品中每个物品的差异度的和最小,这些物品的差异度就是这个最小的和。给定$ N$ 个物品和Q组询问,询问从 $L $到 $R$ 的物品差异度为多少。

    我们设物品$i$和物品$j$之间的差异度为$D$,则

    $D=max{|A_i-A_j|,|B_i-B_j|}$

    $=max{A_i-A_j,A_j-A_i,B_i-B_j,B_j-B_i}$

    我们令$X_i=A_i+B_i,X_j=A_j+B_j,Y_i=A_i-B_i,Y_j=A_j-B_j$。

    则有$D=max{(X_i-X_j)+(Y_i-Y_j),(X_i-X_j)-(Y_i-Y_j),-(X_i-X_j)+(Y_i-Y_j),-(X_i-X_j)-(Y_i-Y_j)}$

    简单化简后,$D=|X_i-X_j|+|Y_i-Y_j|$。

    对于每一件物品,我们求出其对应的$X$值和$Y$值。

    我们建两棵主席树,分别维护$X$值和$Y$值。

    查询一个区间时,我们在两棵主席树上分别查询区间中位数,然后随便维护一下就行了。

    时间复杂度:$O(nlog n)$。

     1 #include<bits/stdc++.h>
     2 #define M 100005
     3 #define L long long
     4 #define INF (2e9)
     5 using namespace std;
     6 
     7 L n,q,A[M]={0},B[M]={0};
     8 
     9 L lc[M*70]={0},rc[M*70]={0},siz[M*70]={0},cnt=0; L sum[M*70]={0};
    10 L root1[M]={0},root2[M]={0};
    11 void add(L &x,L l,L r,L now){
    12     cnt++; lc[cnt]=lc[x]; rc[cnt]=rc[x];
    13     siz[cnt]=siz[x]+1; sum[cnt]=sum[x]+now; x=cnt;
    14     if(l==r) return; L mid=(l+r)>>1;
    15     if(now<=mid) add(lc[x],l,mid,now);
    16     else add(rc[x],mid+1,r,now);
    17 }
    18 L getkth(L x,L y,L l,L r,L k){
    19     if(l==r) return l;
    20     L mid=(l+r)>>1;
    21     if(siz[lc[y]]-siz[lc[x]]<k) return getkth(rc[x],rc[y],mid+1,r,k-(siz[lc[y]]-siz[lc[x]]));
    22     return getkth(lc[x],lc[y],l,mid,k);
    23 }
    24 L getsum(L x,L l,L r,L ll,L rr){
    25     if(ll<=l&&r<=rr) return sum[x];
    26     L mid=(l+r)>>1,res=0;
    27     if(ll<=mid) res+=getsum(lc[x],l,mid,ll,rr);
    28     if(mid<rr) res+=getsum(rc[x],mid+1,r,ll,rr);
    29     return res;
    30 }
    31     
    32 main(){
    33     scanf("%lld%lld",&n,&q);
    34     for(L i=1;i<=n;i++) scanf("%lld",A+i);
    35     for(L i=1;i<=n;i++) scanf("%lld",B+i);
    36     for(L i=1;i<=n;i++){
    37         L upd1=A[i]+B[i],upd2=A[i]-B[i];
    38         root1[i]=root1[i-1]; root2[i]=root2[i-1];
    39         add(root1[i],-INF,INF,upd1);
    40         add(root2[i],-INF,INF,upd2);
    41     }
    42     while(q--){
    43         L l,r,k,h;L res=0,mid; scanf("%lld%lld",&l,&r); 
    44         h=(r-l)/2+1; mid=(l+r)>>1;
    45         k=getkth(root1[l-1],root1[r],-INF,INF,h);
    46         res+=getsum(root1[r],-INF,INF,k,INF)-getsum(root1[l-1],-INF,INF,k,INF);
    47         res-=k*(r-mid+1);
    48         res+=(mid-l)*k;
    49         res-=getsum(root1[r],-INF,INF,-INF,k-1)-getsum(root1[l-1],-INF,INF,-INF,k-1);
    50         
    51         k=getkth(root2[l-1],root2[r],-INF,INF,h);
    52         res+=getsum(root2[r],-INF,INF,k,INF)-getsum(root2[l-1],-INF,INF,k,INF);
    53         res-=k*(r-mid+1);
    54         res+=(mid-l)*k;
    55         res-=getsum(root2[r],-INF,INF,-INF,k-1)-getsum(root2[l-1],-INF,INF,-INF,k-1);
    56         
    57         printf("%.2lf
    ",0.5*res);
    58     }
    59 }
  • 相关阅读:
    【读书笔记】iOS-UDID
    【读书笔记】iOS-优化内存
    【读书笔记】iOS-处理内存警告
    【读书笔记】iOS-方法声明
    【读书笔记】iOS-属性
    【读书笔记】iOS-强类型与弱类型
    【读书笔记】iOS-Objective-C编程
    【读书笔记】iOS-Interface Builder
    【读书笔记】iOS-开发者证书
    【读书笔记】iOS-成为一名开发者
  • 原文地址:https://www.cnblogs.com/xiefengze1/p/10393736.html
Copyright © 2011-2022 走看看