zoukankan      html  css  js  c++  java
  • POJ 3709 KAnonymous Sequence

    POJ_3709

        这个是我第一次做斜率优化的题目,下面的题解没有涉及基本的思路,只是谈了一些自己的感悟。

        个人感觉斜率优化+单调队列最重要的就是维护了一个队列,且对于队首连续的3个元素x,y,z(x<y<z),在任意时刻都不会出现x比y优同时z比x和y都优的情况,下面证明一下为什么有这个特性。

        由于斜率优化+单调队列维护队尾的时候,对于队尾出连续的3个元素i,j,k(i<j<k),如果任意时刻j都不会比i和k更优,那么就会直接把y丢掉。所以,如果此时y在队列中,那么y就一定在某个时刻(也许这个时刻并不会是整数)比x和z更优。同时,过了这个时刻之后,y一定会比x优(这一点能根据不等式推导出来)。根据上面说的几点,既然现在y在队列中,并且x比y优,那么只能说明y比x和z更优的时刻尚未到达,而假如现在z又比y更优的话,类似上面的推导就又能推出y比x和z更优的时刻已经过去了,这时就有矛盾了。

        进一步讲,如果队首有两个连续的元素x,y(x<y),且x比y优,那么此时如果队列中有一个元素z比x和y都优的话,也是可以推出矛盾的。

        有了这个特性以后,我们就可以知道,如果队首有两个连续的元素x,y(x<y),且x比y优,那么队列中所有其他元素都没有x优。这样就太happy啦,因为我们每次进行更新的时候,只要不断地移动队首的位置直到队首的x比下一个元素y更优就停止即可,这时的x一定是最优的。

        当然,如果证明得再严谨一点,还要说明已经从队首出队的点一定不会比当前的点更优,但这个是比较容易证明的。

        此外,这个题目中f[1],f[2],…,f[K-1]这些值是没有任何意义的,因此,我们要么先初始化成INF,要么就干脆不要让这些元素入队,也就是说从K才开始入队操作,当然这样需要首事先把0入队。

    #include<stdio.h>
    #include<string.h>
    #define MAXD 500010
    int N, K, a[MAXD], q[MAXD];
    long long int A[MAXD], f[MAXD];
    void init()
    {
    int i, j, k;
    A[0] = 0;
    scanf("%d%d", &N, &K);
    for(i = 1; i <= N; i ++)
    {
    scanf("%d", &a[i]);
    A[i] = A[i - 1] + a[i];
    }
    }
    long long int getf(int i)
    {
    return f[i] - A[i] + (long long int)i * a[i + 1];
    }
    void solve()
    {
    int i, j, k, front, rear, x, y, z;
    front = rear = 0;
    q[rear ++] = 0;
    f[0] = 0;
    for(i = 1; i <= N; i ++)
    {
    while(front < rear - 1)
    {
    j = q[front], k = q[front + 1];
    if((long long int)i * (a[k + 1] - a[j + 1]) < getf(k) - getf(j))
    break;
    ++ front;
    }
    j = q[front];
    f[i] = getf(j) + A[i] - (long long int)i * a[j + 1];
    if(i + 1 - K >= K)
    {
    q[rear] = i + 1 - K;
    for(j = rear - 1; j > front; j --)
    {
    x = q[j - 1], y = q[j], z = q[j + 1];
    if((getf(z) - getf(y)) * (a[y + 1] - a[x + 1]) > (getf(y) - getf(x)) * (a[z + 1] - a[y + 1]))
    break;
    q[rear = j] = q[j + 1];
    }
    ++ rear;
    }
    }
    printf("%lld\n", f[N]);
    }
    int main()
    {
    int t;
    scanf("%d", &t);
    while(t --)
    {
    init();
    solve();
    }
    return 0;
    }


  • 相关阅读:
    ZYAR20A 亚克力2驱 蓝牙 298寻迹避障机器人 —— 小车按键启动和蜂鸣器报警
    ZYAR20A 亚克力2驱 蓝牙 298寻迹避障机器人 —— 小车指定花式动作
    ZYAR20A 亚克力2驱 蓝牙 298寻迹避障机器人 —— 小车指定花式动作
    ZYAR20A 亚克力2驱 蓝牙 298寻迹避障机器人 —— 小车指定花式动作
    ZYAR20A 亚克力2驱 蓝牙 298寻迹避障机器人 —— 小车前后左右综合实验
    ZYAR20A 亚克力2驱 蓝牙 298寻迹避障机器人 —— 小车前后左右综合实验
    ZYAR20A 亚克力2驱 蓝牙 298寻迹避障机器人 —— 小车前后左右综合实验
    asp中设置session过期时间方法总结
    asp中设置session过期时间方法总结
    ASP.NET关于Session_End触发与否的问题
  • 原文地址:https://www.cnblogs.com/staginner/p/2390499.html
Copyright © 2011-2022 走看看