zoukankan      html  css  js  c++  java
  • [atARC115F]Migration

    称$k$个物品的位置$(a_{1},a_{2},...,a_{k})$为一个状态,并设初始状态为$S$,结束状态为$T$

    定义状态的比较:首先根据$sum_{i=1}^{k}h_{a_{i}}$,即代价小的状态更小,在代价相同时字典序小的状态更小

    考虑二分答案$mid$,接下来即判定$S$能否在代价恒不超过$mid$的限制下转换为$T$

    定义$f(S)$为状态$S$在该限制下所能达到的最小的状态,根据这个转换的传递性以及可逆性,不难发现原条件即等价于$f(S)=f(T)$

    将对一个物品极长的连续若干次操作称为一段,那么总存在一种方案,使得$S$在达到$f(S)$的操作过程中,每一段操作都使得$S$严格更小(这段操作前和这段操作后比较)

    证明比较简单,如果不满足该条件,将这段操作移动到下一次操作该物品的段之前一定不劣,这样会导致段数减小,因此不能无限操作,即得证

    根据这个结论,求$f(S)$即任意执行一段合法(代价仍不超过$mid$)且使得$S$严格变小的操作,并对执行后的这个状态$S'$求$f(S')$即可(根据操作可逆性,有$f(S')=f(S)$)

    每一段操作的效果可以看作二元组$(x,y)$,即使得$a_{x}$变为$y$,上面的两个条件分别对应于:

    1.合法性,等价于$Delta h+sum_{i=1}^{k}h_{a_{i}}le mid$,其中$Delta h$为$a_{x}$到$y$路径上(包括端点)最大权值减去$h_{a_{x}}$的值,即判定$a_{x}$移动到最大权值上时代价是否超过$mid$

    2.使得$S$严格变小,等价于$h_{y}<h_{a_{x}}$或$h_{y}=h_{a_{x}}$且$y<a_{x}$

    根据第2个条件,不难证明一个位置至多被修改$n$次,因此至多$o(nk)$段操作,如果能在$o(log n)$的复杂度内找到(任意)一段操作,即可做到$o(nklog^{2}n)$的复杂度(最外层的二分)

    可以$o(n^{2})$处理出每一个$k$,当$a_{x}=k$时最小的$Delta h$,将之记作$H_{k}$,并用set维护出$min_{x=1}^{n}H_{a_{x}}$以及对应的$x$和$Delta h$取到$H_{a_{x}}$时的$y$即可找到”最容易实现”的操作(即若该操作不可行则其余操作均不可行)

    这样的复杂度仍然不够,考虑优化掉二分,即同时执行求$f(S)$和$f(T)$的过程,每一次操作不需要判定合法性,而是对$ans$取max,选择对$S$或$T$中取的max的值较小的操作先执行,直至$S=T$结束

    (关于$S=T$的判定可以记录$S$和$T$中不同的元素个数,以及要特判$S$或$T$已经取到最小了)

    这样的做法即在过程中利用单调性实现了二分,做到了$o(nklog n)$的复杂度

    还可以进一步优化,将所有$H_{k}$从小到大排序,并从左到右依次执行,将该位置上所有数都移动到其对应点上,暴力移动复杂度是$o(nk)$的,如果用bitset可以优化到$o(frac{nk}{omega})$

    然而还有求$H_{k}$的瓶颈,因此复杂度是$o(n^{2}+frac{nk}{omega})$

    (原题解提到了可以优化到$o(nlog n+k)$,但并没有提到具体方式)

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 2005
     4 #define ll long long
     5 struct Edge{
     6     int nex,to;
     7 }edge[N<<1];
     8 priority_queue<pair<int,int> >qS,qT;
     9 int E,n,m,x,y,diff,head[N],h[N],S[N],T[N],mx[N],pos[N],H[N];
    10 ll sumS,sumT,ans;
    11 void add(int x,int y){
    12     edge[E].nex=head[x];
    13     edge[E].to=y;
    14     head[x]=E++;
    15 }
    16 void dfs(int k,int fa,int sh){
    17     sh=max(sh,h[k]);
    18     mx[k]=sh;
    19     for(int i=head[k];i!=-1;i=edge[i].nex)
    20         if (edge[i].to!=fa)dfs(edge[i].to,k,sh);
    21 }
    22 int main(){
    23     scanf("%d",&n);
    24     for(int i=1;i<=n;i++)scanf("%d",&h[i]);
    25     memset(head,-1,sizeof(head));
    26     for(int i=1;i<n;i++){
    27         scanf("%d%d",&x,&y);
    28         add(x,y);
    29         add(y,x);
    30     }
    31     for(int i=1;i<=n;i++){
    32         dfs(i,0,0);
    33         H[i]=0x3f3f3f3f;
    34         for(int j=1;j<=n;j++)
    35             if ((h[j]<h[i])||(h[j]==h[i])&&(j<i)){
    36                 if (mx[j]-h[i]<H[i]){
    37                     H[i]=mx[j]-h[i];
    38                     pos[i]=j;
    39                 }
    40             }
    41     }
    42     scanf("%d",&m);
    43     for(int i=1;i<=m;i++){
    44         scanf("%d%d",&S[i],&T[i]);
    45         sumS+=h[S[i]],sumT+=h[T[i]];
    46         qS.push(make_pair(-H[S[i]],i));
    47         qT.push(make_pair(-H[T[i]],i));
    48         if (S[i]!=T[i])diff++;
    49     }
    50     ans=max(sumS,sumT);
    51     int tot=0;
    52     while (diff){
    53         int kS=qS.top().second,kT=qT.top().second;
    54         ll ansS=H[S[kS]]+sumS,ansT=H[T[kT]]+sumT;
    55         if (!pos[S[kS]])ansS=ansT+1;
    56         if (!pos[T[kT]])ansT=ansS+1;
    57         ans=max(ans,min(ansS,ansT));
    58         if (ansS<ansT){
    59             sumS+=h[pos[S[kS]]]-h[S[kS]];
    60             diff+=(pos[S[kS]]!=T[kS])-(S[kS]!=T[kS]);
    61             qS.pop();
    62             S[kS]=pos[S[kS]];
    63             qS.push(make_pair(-H[S[kS]],kS));
    64         }
    65         else{
    66             sumT+=h[pos[T[kT]]]-h[T[kT]];
    67             diff+=(pos[T[kT]]!=S[kT])-(T[kT]!=S[kT]);
    68             qT.pop();
    69             T[kT]=pos[T[kT]];
    70             qT.push(make_pair(-H[T[kT]],kT));
    71         }
    72     }
    73     printf("%lld",ans);
    74 }
    View Code
  • 相关阅读:
    hdu 1875 畅通project再续(kruskal算法计算最小生成树)
    Http post提交和get提交
    我的软考之路(五)——数据结构与算法(3)之图
    WPF 布局控件 之 DockPanel
    oracle存储结构
    马化腾最想做的事情是人工智能
    Android_Zip解压缩工具
    Unity的 Stats 窗体, Batched、SetPass、Draw Call 等
    尝试 “实验楼”在线教育平台
    POJ 3181 Dollar Dayz 01全然背包问题
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/14593688.html
Copyright © 2011-2022 走看看