Official

F - Minimize Bounding Square Editorial by physics0523


この問題にはいくつかのヒントが用意されています。各項目をクリックすると内容を見ることができます。

ヒント1 この問題は、 xx 座標と yy 座標とを分離して考えることができます。
ヒント2 この問題では、ある貪欲法が成立します。
解説 各点の xx 座標の列を XX'yy 座標の列を YY' とします。
これ以上点の移動が行えない時、描くべき正方形の一辺の長さの最小値は max(max(X)min(X),max(Y)min(Y))\max(\max(X')-\min(X'), \max(Y')-\min(Y')) となります。
max\max に入った 22 つの項 χ=max(X)min(X)\chi=\max(X')-\min(X')γ=max(Y)min(Y)\gamma=\max(Y')-\min(Y') に関して場合分けします。
  • χ<γ\chi < \gamma の場合
    • xx 座標を変更しても最小化すべき値は変化しないのでいったん放置してよいです。 yy 座標に関して、 max(Y)\max(Y')min(Y)\min(Y') のうち個数が少ない方を全て 11 変更(適切な方向に)できるならそうして γ\gamma11 減らすべきで、できないならもう解を改善する余地はありません。
  • χ>γ\chi > \gamma の場合も同様です。
  • χ=γ\chi = \gamma の場合
    • この場合、 χ<γ\chi < \gamma とみなして γ\gamma を先に 11 変更してもよければ、 χ,γ\chi,\gamma を同時に 11 変更するようにしても構いません。
重大な注意として、愚直に 11 ずつ変更していては座標 10910^9 の制約より実行時間制限に間に合わせるのは困難です。
この場合は、 min(X),max(X),min(Y),max(Y)\min(X'), \max(X'), \min(Y'), \max(Y') の値が全体で高々 2N2N 回しか変化しないことを念頭に置き、これらの値が変化するまでまとめて操作を行いましょう。
略証 まず、明らかに操作の過程で min(X)\min(X') を小さくする / max(X)\max(X') を大きくするべきではありません。これより、この両者を近づけていくような変更のみを考えます。
min(X)\min(X')max(X)\max(X') は、動かせば動かすほど動かす必要のある点数が増えていきます。つまり、 11 動かすのに必要なコストが(広義)単調増加していきます。
この性質から、 χ\chi の値を決め打った時、上記の貪欲法に従わない動かし方から従う動かし方へと、点を動かす回数を増やさずにに変更できることが示せます。

実装例 (C++):

Copy
  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. using pl=pair<long long,long long>;
  4. int main(){
  5. long long n,k;
  6. cin >> n >> k;
  7. vector<long long> x(n),y(n);
  8. map<long long,long long> mx,my;
  9. for(long long i=0;i<n;i++){
  10. cin >> x[i] >> y[i];
  11. mx[x[i]]++;
  12. my[y[i]]++;
  13. }
  14. vector<pl> xv,yv;
  15. for(auto &nx : mx){
  16. xv.push_back(nx);
  17. }
  18. for(auto &nx : my){
  19. yv.push_back(nx);
  20. }
  21. long long xl=0,xr=xv.size()-1;
  22. long long yl=0,yr=yv.size()-1;
  23. while(k>0){
  24. long long gx=xv[xr].first-xv[xl].first;
  25. long long gy=yv[yr].first-yv[yl].first;
  26. long long fx,fy;
  27. long long hx,hy;
  28. long long cx,cy;
  29. if(gx!=0){
  30. if(xv[xl].second<xv[xr].second){
  31. hx=xv[xl+1].first-xv[xl].first;
  32. cx=xv[xl].second;
  33. fx=-1;
  34. }
  35. else{
  36. hx=xv[xr].first-xv[xr-1].first;
  37. cx=xv[xr].second;
  38. fx=1;
  39. }
  40. }
  41. if(gy!=0){
  42. if(yv[yl].second<yv[yr].second){
  43. hy=yv[yl+1].first-yv[yl].first;
  44. cy=yv[yl].second;
  45. fy=-1;
  46. }
  47. else{
  48. hy=yv[yr].first-yv[yr-1].first;
  49. cy=yv[yr].second;
  50. fy=1;
  51. }
  52. }
  53. if(gx==0 && gy==0){break;}
  54. else if(gx<gy){
  55. // shorten y
  56. long long opt=min({k/cy,hy,gy-gx});
  57. if(opt==0){break;}
  58. k-=cy*opt;
  59. if(fy==-1){yv[yl].first+=opt;}
  60. else{yv[yr].first-=opt;}
  61. }
  62. else if(gx>gy){
  63. // shorten x
  64. long long opt=min({k/cx,hx,gx-gy});
  65. if(opt==0){break;}
  66. k-=cx*opt;
  67. if(fx==-1){xv[xl].first+=opt;}
  68. else{xv[xr].first-=opt;}
  69. }
  70. else{
  71. // once x==y, let's keep it
  72. // shorten x&y
  73. long long opt=min({k/(cx+cy),hx,hy});
  74. if(opt==0){break;}
  75. k-=(cx+cy)*opt;
  76. if(fy==-1){yv[yl].first+=opt;}
  77. else{yv[yr].first-=opt;}
  78. if(fx==-1){xv[xl].first+=opt;}
  79. else{xv[xr].first-=opt;}
  80. }
  81. if(xl!=xr){
  82. if(xv[xl].first==xv[xl+1].first){
  83. xv[xl+1].second+=xv[xl].second;
  84. xl++;
  85. }
  86. else if(xv[xr].first==xv[xr-1].first){
  87. xv[xr-1].second+=xv[xr].second;
  88. xr--;
  89. }
  90. }
  91. if(yl!=yr){
  92. if(yv[yl].first==yv[yl+1].first){
  93. yv[yl+1].second+=yv[yl].second;
  94. yl++;
  95. }
  96. else if(yv[yr].first==yv[yr-1].first){
  97. yv[yr-1].second+=yv[yr].second;
  98. yr--;
  99. }
  100. }
  101. }
  102. {
  103. long long gx=xv[xr].first-xv[xl].first;
  104. long long gy=yv[yr].first-yv[yl].first;
  105. cout << max(gx,gy) << "\n";
  106. }
  107. return 0;
  108. }
#include<bits/stdc++.h>

using namespace std;
using pl=pair<long long,long long>;

int main(){
  long long n,k;
  cin >> n >> k;

  vector<long long> x(n),y(n);
  map<long long,long long> mx,my;
  for(long long i=0;i<n;i++){
    cin >> x[i] >> y[i];
    mx[x[i]]++;
    my[y[i]]++;
  }

  vector<pl> xv,yv;
  for(auto &nx : mx){
    xv.push_back(nx);
  }
  for(auto &nx : my){
    yv.push_back(nx);
  }

  long long xl=0,xr=xv.size()-1;
  long long yl=0,yr=yv.size()-1;

  while(k>0){
    long long gx=xv[xr].first-xv[xl].first;
    long long gy=yv[yr].first-yv[yl].first;

    long long fx,fy;
    long long hx,hy;
    long long cx,cy;
    if(gx!=0){
      if(xv[xl].second<xv[xr].second){
        hx=xv[xl+1].first-xv[xl].first;
        cx=xv[xl].second;
        fx=-1;
      }
      else{
        hx=xv[xr].first-xv[xr-1].first;
        cx=xv[xr].second;
        fx=1;
      }
    }
    if(gy!=0){
      if(yv[yl].second<yv[yr].second){
        hy=yv[yl+1].first-yv[yl].first;
        cy=yv[yl].second;
        fy=-1;
      }
      else{
        hy=yv[yr].first-yv[yr-1].first;
        cy=yv[yr].second;
        fy=1;
      }
    }

    if(gx==0 && gy==0){break;}
    else if(gx<gy){
      // shorten y
      long long opt=min({k/cy,hy,gy-gx});
      if(opt==0){break;}
      k-=cy*opt;
      if(fy==-1){yv[yl].first+=opt;}
      else{yv[yr].first-=opt;}
    }
    else if(gx>gy){
      // shorten x
      long long opt=min({k/cx,hx,gx-gy});
      if(opt==0){break;}
      k-=cx*opt;
      if(fx==-1){xv[xl].first+=opt;}
      else{xv[xr].first-=opt;}
    }
    else{
      // once x==y, let's keep it
      // shorten x&y
      long long opt=min({k/(cx+cy),hx,hy});
      if(opt==0){break;}
      k-=(cx+cy)*opt;

      if(fy==-1){yv[yl].first+=opt;}
      else{yv[yr].first-=opt;}
      
      if(fx==-1){xv[xl].first+=opt;}
      else{xv[xr].first-=opt;}
    }

    if(xl!=xr){
      if(xv[xl].first==xv[xl+1].first){
        xv[xl+1].second+=xv[xl].second;
        xl++;
      }
      else if(xv[xr].first==xv[xr-1].first){
        xv[xr-1].second+=xv[xr].second;
        xr--;
      }
    }
    if(yl!=yr){
      if(yv[yl].first==yv[yl+1].first){
        yv[yl+1].second+=yv[yl].second;
        yl++;
      }
      else if(yv[yr].first==yv[yr-1].first){
        yv[yr-1].second+=yv[yr].second;
        yr--;
      }
    }
  }

  {
    long long gx=xv[xr].first-xv[xl].first;
    long long gy=yv[yr].first-yv[yl].first;
    cout << max(gx,gy) << "\n";
  }
  return 0;
}

posted:
last update:



2025-04-27 (Sun)
13:54:32 +00:00