【2018南京】 Tournament (dp + 决策单调性 + wqs 二分)

论坛 期权论坛 脚本     
匿名技术用户   2021-1-6 08:48   26   0

There are NN villagers (including the village chief) living in Number Village. Interestingly, all of their houses lie on a straight line. The house of the ii-th villager (0\leq i<N0i<N) lies exactly a_iaikilometers to the east of the village chief's house. (For simplicity, the 00-th villager is the village chief, so a_0=0a0=0.)

Recently, a tournament is going to be held in Number Village, in which everyone in the village will participate.

For the convenience of villagers, the organizer plans to build KK stadiums. The stadium can be built anywhere in the village, even at the same place as any villager's house.

However, the organizer wants the traffic cost to be minimized. The traffic cost is defined by \sum_{i=0}^{N-1} \min_{j=0}^{K-1} D(a_i, s_j)i=0N1minj=0K1D(ai,sj), where D(a_i, s_j)D(ai,sj) is the distance between the ii-th villager's house and the jj-th stadium.

Your task is to calculate the minimal traffic cost (rounded down to the nearest integer), given N, KN,K and a_iai.

Input

The first line contains two positive integers N,KN,K (K\leq N\leq 3\times 10^ 5KN3×105).

The second line contains NN non-negative integers a_0,a_1,\cdots,a_{N-1}a0,a1,,aN1 (0=a_0<a_1<\cdots<a_{N-1}\leq 10^ 90=a0<a1<<aN1109).

Output

Print a single integer \text{---}— the minimal traffic cost rounded down to the nearest integer.

样例输入1复制

5 2
0 4 7 9 10

样例输出1复制

7

样例输入2复制

9 3
0 1 10 11 20 21 22 30 32

样例输出2复制

23

题目来源

ACM-ICPC Nanjing Onsite 2018

SOLUTION:

我这份题解并没有a,可能是二分的地方常数太大导致T了,但是可以当作模板

wqs二分之后,变成了O^2的dp,然后使用单调队列来进行优化

一类导数递增求最小值,或者导数递减求最大值,需要使用单调队列

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f3f3f3f3f
#define N 300010

ll n,k,s[N],f[N],w[N],ans=0;
int q[N];

ll a[N]; int isx[N];
inline ll calc(int &j,int &i)
{
    int mid=i+j+1>>1;
    ll now=s[mid]-s[mid-1];
  //  return f[j]+s[i]+s[j]-2*s[mid]+((i-j)&1?now:0);
    mid=i+j+1>>1;
    return f[j]+(s[i]-s[mid]-(i-mid)*a[mid])+((mid-j-1)*a[mid]-(s[mid-1]-s[j]));

}
inline bool better(int &k1,int &k2,int &i)
{
    ll val1=calc(k1,i),val2=calc(k2,i);
    if(val2<val1)
        return 1;
    if(val1<val2)
        return 0;
    return w[k2]<=w[k1];
}

inline int bound(int &a,int &b,int o)
{
    int l=b+1,r=o?o:n+1,ans=r+1;
    while(l<=r)
    {
        int mid=l+r>>1;
       // if(calc(a,mid)>=calc(b,mid))ans=mid,r=mid-1;
        if(better(a,b,mid))ans=mid,r=mid-1;
        else l=mid+1;
    } return ans;
}

inline int  jud(ll mid)
{
    int qh=1,qt=0;
    q[++qt]=0;
    for(int i=1;i<=n;++i)
    {
        while(qh<qt&&isx[qh]<=i)++qh;
        f[i]=calc(q[qh],i)+mid;
        w[i]=w[q[qh]]+1;
        while(qh<qt&&isx[qt-1]>=bound(q[qt],i,isx[qt-1]+1))
            --qt;
        isx[qt]=bound(q[qt],i,0);
        q[++qt]=i;
    }
    return w[n];
}inline int read()
{
 int X=0; bool flag=1; char ch=getchar();
 while(ch<'0'||ch>'9') {if(ch=='-') flag=0; ch=getchar();}
 while(ch>='0'&&ch<='9') {X=(X<<1)+(X<<3)+ch-'0'; ch=getchar();}
 if(flag) return X;
 return ~(X-1);
}

signed main()
{
    n=read(); k=read();
        ans=0;
        for(int i=1;i<=n;i++)isx[i]=0;
        for(ll i=1;i<=n;i++)
        {
            s[i]=read();
            a[i]=s[i];
            s[i]+=s[i-1];
        }
        ll l=0,r=s[n];
        while(l<=r)
        {
            ll mid=l+r>>1;
            if(jud(mid)<=k)
            {
                r=mid-1;
                ans=f[n]-k*mid;
            }
            else
                l=mid+1;
        }
        printf("%lld\n",ans);

    return 0;
}

  

转载于:https://www.cnblogs.com/zhangbuang/p/11253761.html

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:7942463
帖子:1588486
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP