公式

G - Specified Range Sums 解説 by en_translator


Out of nowhere, let us replace the constraints \(\sum_{j=l}^{r} A_j = S_i\) with \(B(k) = \sum_{i=1}^{k} A_i\) for convenience.
Then, the constraint \(\sum_{j=l}^{r} A_j = S_i\) is substituted by \(B_{r} - B_{l-1} = S\).

Let us rephrase the constraints on the sequence using \(B\):

  • \(B_{R_i} - B_{L_i-1} = S_i\) ( \(1 \le i \le M\) )
  • \(B_{j} - B_{j-1} \ge 1\) ( \(1 \le j \le N\) )

We further deform the constraints to turn the equality into inequalities.

  • \(B_{R_i} - B_{L_i-1} \ge S_i\) ( \(1 \le i \le M\) )
  • \(B_{R_i} - B_{L_i-1} \le S_i\) ( \(1 \le i \le M\) )
  • \(B_{j} - B_{j-1} \ge 1\) ( \(1 \le j \le N\) )

The problem to be solved is represented as the following linear programming (LP) problem:

\[ \begin{aligned} &\text{minimize} & & B_N \\ &\text{subject to} & & B_{R_i} - B_{L_i-1} \ge S_i \ ( 1 \le i \le M ) \\ & & & B_{R_i} - B_{L_i-1} \le S_i \ ( 1 \le i \le M ) \\ & & & B_{j} - B_{j-1} \ge 1\ ( 1 \le j \le N ) \end{aligned} \]

Here, notice that all the constraints are represented in the form \(B_i + c \ge B_j\). This is a special variant of LP that is easier to solved, and informally called Cow Game (in Japanese competitive programming community). Article 1 Article 2 Article 3 Article 4 Article 5 (all in Japanese)
(The name Cow Game originates from a problem arranging cows, which caused the trick widely known. Judge 1 Judge 2)

The objective function of the original Cow Game is maximizing a specific variable, but one can set the following LP to obtain that form.
The answer to the original problem is \(-1\) times the optimal value for the objective function of the following LP.

\[ \begin{aligned} &\text{maximize} & & B_0 \\ &\text{subject to} & & B_{R_i} - B_{L_i-1} \ge S_i \ ( 1 \le i \le M ) \\ & & & B_{R_i} - B_{L_i-1} \le S_i \ ( 1 \le i \le M ) \\ & & & B_{j} - B_{j-1} \ge 1\ ( 1 \le j \le N ) \\ & & & B_N = 0 \\ \end{aligned} \]

All that left is to construct an appropriate graph according to the form of the LP, and solve the shortest-path problem using Bellman-Ford algorithm.

Sample code (C++):

#include<bits/stdc++.h>

using namespace std;

int main(){
  long long n,m;
  cin >> n >> m;
  vector<long long> l(m),r(m),s(m);
  for(long long i=0;i<m;i++){
    cin >> l[i] >> r[i] >> s[i];
  }

  vector<array<long long,3>> eg;
  for(long long i=1;i<=n;i++){
    eg.push_back({i,i-1,-1});
  }
  for(long long i=0;i<m;i++){
    eg.push_back({r[i],l[i]-1,-s[i]});
    eg.push_back({l[i]-1,r[i],s[i]});
  }

  // for(auto &nx : eg){
  //   cout << nx[0] << " -> " << nx[1] << " : " << nx[2] << "\n";
  // }

  vector<long long> d(n+1,8e18);
  d[n]=0;
  bool upd;
  for(long long tr=0;tr<2*(n+m)+5;tr++){
    upd=false;
    for(auto &nx : eg){
      long long nd=d[nx[0]]+nx[2];
      if(d[nx[1]] > nd){
        d[nx[1]]=nd;
        upd=true;
      }
    }
  }
  
  if(upd){cout << "-1\n"; return 0;}
  cout << -d[0] << "\n";
  return 0;
}

投稿日時:
最終更新: