【BZOJ-1367】sequence 可并堆+中位数

1367: [Baltic2004]sequence

Time Limit: 20 Sec  Memory Limit: 64 MB
Submit: 932  Solved: 348
[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

Source

Solution

论文中的例题,非常吼啊....思想巧妙

Code

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
int read()
{
    int x=0,f=1; char ch=getchar();
    while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
    while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}
#define maxn 1000100
long long ans;
int n,data[maxn],root[maxn],L[maxn],R[maxn],cnt[maxn],tot;
struct LeftTreeNode
{
    int sz,son[maxn][2],d[maxn],size[maxn],a[maxn];
//    LeftTreeNode () 
//        {
//            sz=0;memset(son,0,sizeof(son));memset(size,0,sizeof(size));
//            memset(cnt,0,sizeof(cnt));memset(a,0,sizeof(a));memset(d,0,sizeof(d));
//        }
    int Merge(int x,int y)
        {
            if (!x) return y;
            if (!y) return x;
            if (a[x]<a[y]) swap(x,y);
            son[x][1]=Merge(son[x][1],y);
            size[x]=size[son[x][0]]+size[son[x][1]]+1;
            if (d[son[x][1]]>d[son[x][0]]) swap(son[x][0],son[x][1]);
            d[x]=d[son[x][1]]+1;
            return x;
        }
    int Push(int x)
        {
            a[++sz]=x; size[sz]=1;
            son[sz][0]=son[sz][1]=d[sz]=0;
            return sz;
        }
    int Pop(int x) {return Merge(son[x][0],son[x][1]);}
    int Top(int x) {return a[x];}
    int Size(int x) {return size[x];}
}LTHeap;
int main()
{
    n=read();
    for (int i=1; i<=n; i++) data[i]=read()-i;
    for (int i=1; i<=n; i++)
        {
            tot++;
            root[tot]=LTHeap.Push(data[i]); cnt[tot]=1; L[tot]=R[tot]=i;
            while (tot>1 && LTHeap.Top(root[tot])<LTHeap.Top(root[tot-1]))
                {
                    tot--;
                    root[tot]=LTHeap.Merge(root[tot],root[tot+1]); cnt[tot]+=cnt[tot+1]; R[tot]=R[tot+1];
                    while (LTHeap.Size(root[tot])*2>cnt[tot]+1) 
                        root[tot]=LTHeap.Pop(root[tot]);
                }
        }
    for (int i=1; i<=tot; i++)
        for (int j=L[i],top=LTHeap.Top(root[i]); j<=R[i]; j++)
            ans+=abs(data[j]-top);
    printf("%lld
",ans);
    return 0;
}

被YveH发现了...

原文地址:https://www.cnblogs.com/DaD3zZ-Beyonder/p/5469217.html