zoukankan      html  css  js  c++  java
  • uoj49 轴仓库

    题意:

    n叠箱子排成一线,第i叠箱子坐标为xi,竖直方向叠着ai个箱子。

    可以花费+1s左移或右移一位,也可以在瞬间搬起一个位置的箱子,或将怀里的有且仅有一个箱子放下。

    任意选择起点s(可以不与xi重合),初始时两手空空。

    求从s出发,在T秒内,最多能够将多少个箱子集中在s点上。

    n<=5e5.

    标程:

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 using namespace std;
     5 typedef long long ll;
     6 const int N=500005;
     7 ll n,t,x[N],a[N],sum[N],sumk[N],ss,l,r,ans;
     8 bool check(ll k)
     9 {
    10     ll l=1,r=lower_bound(sum+1,sum+n+1,k)-sum;
    11     ll lc=a[1],rc=k-sum[r-1];
    12     for (int i=1;i<=n;i++)
    13     {
    14         while (l<i&&r<=n&&x[i]-x[l]>x[r]-x[i]) 
    15         {
    16             ll mm=min(lc,a[r]-rc);
    17             lc-=mm;rc+=mm;
    18             if (lc==0) lc=a[++l];
    19             if (rc==a[r]) r++,rc=0;
    20         }
    21         ss=sumk[r-1]-sumk[i]-x[i]*(sum[r-1]-sum[i]) + x[i]*(sum[i]-sum[l])-(sumk[i]-sumk[l])
    22         +lc*(x[i]-x[l])+rc*(x[r]-x[i]);
    23         if (ss<=t) return 1;
    24     }
    25     return 0;
    26 }
    27 int main()
    28 {
    29     scanf("%lld%lld",&n,&t);t/=2;
    30     for (int i=1;i<=n;i++) scanf("%lld",&x[i]);
    31     for (int i=1;i<=n;i++) scanf("%lld",&a[i]),sum[i]=sum[i-1]+a[i],sumk[i]=sumk[i-1]+a[i]*x[i];
    32     l=1;r=sum[n];
    33     while (l<=r)
    34     {
    35         ll mid=(l+r)>>1;
    36         if (check(mid)) l=mid+1,ans=mid;else r=mid-1;
    37     }
    38     printf("%lld\n",ans);
    39    return 0;
    40 }

    题解:双指针+二分答案

    直接双指针扫描不行吗?因为x坐标并不连续,而且有ai限制,所以选取区间左右端点不一定单调!我们希望能够转换问题。

    二分答案取k个物品,如果存在一个S,使得S选取与之距离最近的k个物品时间花费<=T,那么这个k视为可达。

    某性质:在相邻两个xi之间选取的S,在选物区间固定的情况下,花费时间T是一个一次函数(单调)。因而极值一定在有物品的点上,对于S只用枚举关键点即可。

    这样我们就可以用双指针来解决问题了。(我在双指针这里想了好久)

    从共选取k个物品入手,左右端点移动相同的长度。

    设置lc和rc分别表示l指针指向的那一块取了lc个,最后r指针指向的那一块取了rc个。

     如下图所示,当x[i]-x[l]>x[r]-x[i]时,移动左右端点,选择min(lc,a[r]-rc)的长度移动。

    然后用前缀和计算一下所用的时间(注意公式的正确性)。

    时间复杂度O(nlog(sum)).

  • 相关阅读:
    左偏树
    论在Windows下远程连接Ubuntu
    ZOJ 3711 Give Me Your Hand
    SGU 495. Kids and Prizes
    POJ 2151 Check the difficulty of problems
    CodeForces 148D. Bag of mice
    HDU 3631 Shortest Path
    HDU 1869 六度分离
    HDU 2544 最短路
    HDU 3584 Cube
  • 原文地址:https://www.cnblogs.com/Scx117/p/8697129.html
Copyright © 2011-2022 走看看