joigsc2022_e 题解

翻译

有长度为 \(n\) 的序列 \(a\)\(L\),你需要对于每个 \(x \in[1,n]\) 求出若把第 \(x\) 个数到第 \(n\) 个数依次装入容量为 \(L\) 的箱子中(每个数的体积为它的值,若箱子装不下了,则会使用另一个空箱子)会使用多少个箱子以及最后一个箱子的质量。

题解

考虑一个显然的暴力,用二分找出每个盒子最装下那些数,总复杂度最坏是 \(O(n^2 \log n)\)

然后其实可以考虑一个记忆化。

假设对于 \(x = 1\) 我们发现会在编号为 \(a,b,c\) 的数处更换一个空盒子。

那么计算某个答案时也在 \(a\) 处更换盒子,那么用当前答案合并上 \(x = a\) 的答案。

然后考虑复杂度。

\(f_i\)\(x = i\) 时的答案。

那么为了求出答案显然会进行 \(f_i\) 次二分。

那么显然每一次二分都是建立在当前点的答案没有被求出的情况下。

所以我们发现每次二分都是用 \(\log n\) 的时间求出了一个点的答案,且一个点的答案只会被二分一次。

而又一共只有 \(n\) 个点。

所以总复杂度就是 \(O(n \log n)\)

但是其实发现这个相当于一个从后往前的 dp。

记录 \(f_i\)\(x = i\) 时的答案。

那么 \(f_i = f_j + 1\)(求用多少个箱子的转移方程,求最后一个箱子的质量的转移类似,不过多赘述)其中 \(j\) 表示从第 \(i\) 个数开始最多装可以装到的数。

然后我们发现这个 \(j\) 可以在 dp 时把扫到的所有数放到一个队列里面,记录队列里的数的总和,如果大于 \(L\) 就把队尾弹出,那么我们发现 \(j\) 就是队尾的元素下标。

也就是说这个 dp 可以 \(O(n)\) 求。

这里给出考场上写的记忆化算法。

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=200001;
pair<int,int> ans[maxn];
int pre[maxn];
int a[maxn],L,n;
pair<int,int> work(int x)
{
  if(ans[x].second!=0)
  {
    return ans[x];
  }
  int now=x;
  int cnt=0,val;
  queue<int> inti;
  while(now<=n)
  {
  inti.push(now);
    int l=now,r=n+1;
    while(l+1<r)
    {
      int mid=(l+r)/2;
      if(pre[mid]-pre[now-1]>L)
      {
        r=mid;
      }
      else
      {
        l=mid;
      }
    }
    cnt++;
    val=pre[l]-pre[now-1];
    now=r;
    if(ans[now].second!=0)
    {
      pair<int,int> ret;
      int  f=ans[now].first+cnt;
      ret.second=ans[now].second;
      ret.first=ans[now].first+cnt;
      while(inti.size()>0)
      {
        ans[inti.front()].second=ret.second;
        ans[inti.front()].first=f;
        f--;
        inti.pop();
      }
      return ret;
    }
  }
  int f=cnt;
  while(inti.size()>0)
  {
    ans[inti.front()].first=f;
    f--;
    ans[inti.front()].second=val;
    inti.pop();
  }
  return ans[x];
}
signed main()
{
  ios::sync_with_stdio(false);
  cin>>n>>L;
  for(int i=1;i<=n;++i)
  {
    cin>>a[i];
    pre[i]=pre[i-1]+a[i];
  }
  for(int i=1;i<=n;++i)
  {
    pair<int,int> anser;
    anser=work(i);
  }
  return 0;
}
posted @ 2024-01-31 00:00  ChiFAN鸭  阅读(8)  评论(0编辑  收藏  举报