bzoj1367 [Baltic2004]sequence

1367: [Baltic2004]sequence

Time Limit: 20 Sec  Memory Limit: 64 MB
Submit: 1473  Solved: 604
[Submit][Status][Discuss]

Description

Input

Output

一个整数R

Sample Input

7
9
4
8
20
14
15
18

Sample Output

13

HINT

所求的Z序列为6,7,8,13,14,15,18.
R=13

分析:左偏树的应用.

          减弱一下条件,如果最后求得的序列可以是非严格递增的.那么可以将原序列分为两类,一类是单调递增的,对于这一类只需要让Z序列等于t序列中的每一个数就可以了.一类是单调下降的,根据绝对值的几何意义,如果将这段序列的t全部变成它的中位数,那么答案就是最优的.那么我们只需要将t序列按照上述两种分类来分段即可.

          这样会有一个问题,后面的中位数比前面的小,那么就不满足Z序列单调上升的这个条件了.这时将当前段与上一段合并,再求出新的中位数即可.如何快速求中位数是优先队列的一个经典应用,但是合并两段非常慢,那么利用可并堆,左偏树就可以了.

          题目要求的是严格递增,那么在读入的时候将t序列的所有数-i即可.相当于就是一个偏移.

          注意左偏树序号的问题,动态加点.

#include <cstdio>
#include <cmath>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

typedef long long ll;
int n,t[1000010],tot,cnt,dist[1000010],id[1000010],l[1000010],r[1000010],sizee[1000010],v[1000010],L[1000010],R[1000010];
ll ans;

int hebing(int x,int y)
{
    if (!x || !y)
        return x + y;
    if (v[x] < v[y])
        swap(x,y);
    r[x] = hebing(r[x],y);
    sizee[x] = sizee[r[x]] + sizee[l[x]] + 1;
    if (dist[r[x]] > dist[l[x]])
        swap(r[x],l[x]);
    dist[x] = dist[r[x]] + 1;
    return x;
}

void pop(int x)
{
    id[x] = hebing(l[id[x]],r[id[x]]);
}

void newone(int x)
{
    v[++tot] = x;
    sizee[tot] = 1;
    l[tot] = r[tot] = dist[tot] = 0;
    id[cnt] = tot;
}

void solve()
{
    for (int i = 1; i <= n; i++)
    {
        ++cnt;
        newone(t[i]);
        L[cnt] = R[cnt] = i;
        while (cnt > 1 && v[id[cnt]] < v[id[cnt - 1]])
        {
            cnt--;
            id[cnt] = hebing(id[cnt],id[cnt + 1]);
            R[cnt] = R[cnt + 1];
            while (sizee[id[cnt]] * 2 > R[cnt] - L[cnt] + 2)
                pop(cnt);
        }
    }
}

int main()
{
    scanf("%d",&n);
    for (int i = 1; i <= n; i++)
    {
        scanf("%d",&t[i]);
        t[i] -= i;
    }
    solve();
    for (int i = 1; i <= cnt; i++)
    {
        int temp = v[id[i]];
        for (int j = L[i]; j <= R[i]; j++)
            ans += abs(temp - t[j]);
    }
    printf("%lld\n",ans);

    return 0;
}

 

posted @ 2017-12-22 16:15  zbtrs  阅读(242)  评论(0编辑  收藏  举报