zoukankan      html  css  js  c++  java
  • 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
    ",ans);
    
        return 0;
    }
  • 相关阅读:
    javascript得知
    一旦配置oracle em经验
    windows 下一个mysql password忘记改变
    彩色图像--图像切 色彩空间切割
    Delphi 6 Web Services初步评估之三(转)
    Delphi 用Web App Debugger简单调试ISAPI 转
    Delphi socket() 函数的应用
    用Delphi实现WinSocket高级应用
    delphi编写winsocket的流程
    Delphi使用NativeXml访问XML文件
  • 原文地址:https://www.cnblogs.com/zbtrs/p/8086499.html
Copyright © 2011-2022 走看看