# BZOJ1367【Baltic2004】sequence

## 题面

### Sample Input

7
9
4
8
20
14
15
18


### Sample Output

13


R=13

## Solution

• $a_1 \le a_2 \le ... \le a_n$, 此时$b_n = a_n$
• $a_1 \ge a_2 \ge ... \ge a_n$, 此时$b_n = \{a_n\}的中位数$

#include <cstdio>
#include <cctype>
#include <algorithm>
#include <cmath>

namespace Zeonfai
{
inline int getInt()
{
int a = 0, sgn = 1;
char c;

while(! isdigit(c = getchar()))
if(c == '-')
sgn *= -1;

while(isdigit(c))
a = a * 10 + c - '0', c = getchar();

return a * sgn;
}
}

const int N = (int)1e6;
int a[N], cnt;

struct section
{
int L, R, w;
}sec[N];

struct splayTrees
{
struct node
{
int suc[2], pre, sz, w;
}nd[N];

int rt[N];

inline void newNode(int u, int w)
{
nd[u].w = w, nd[u].suc[0] = nd[u].suc[1] = nd[u].pre = -1, nd[u].sz = 1;
}

inline void update(int u)
{
nd[u].sz = 1;

for(int i = 0; i < 2; ++ i)
if(~ nd[u].suc[i])
nd[u].sz += nd[nd[u].suc[i]].sz;
}

inline int getRelation(int u)
{
if(! (~ nd[u].pre))
return -1;

return u == nd[nd[u].pre].suc[1];
}

inline void rotate(int u)
{
int pre = nd[u].pre, prepre = nd[pre].pre, k = getRelation(u);

if(~ nd[u].suc[k ^ 1])
nd[nd[u].suc[k ^ 1]].pre = pre;

nd[pre].suc[k] = nd[u].suc[k ^ 1];
nd[u].suc[k ^ 1] = pre;
nd[u].pre = nd[pre].pre;

if(~ prepre)
nd[prepre].suc[getRelation(pre)] = u;

nd[pre].pre = u;
update(pre), update(u);
}

inline void splay(int a, int u)
{
while(~ nd[u].pre)
{
int pre = nd[u].pre;

if(~ nd[pre].pre)
rotate(getRelation(pre) == getRelation(u) ? pre : u);

rotate(u);
}

rt[a] = u;
}

void _insert(int a, int u, int v)
{
++ nd[u].sz;

if(nd[v].w < nd[u].w)
{
if(! (~ nd[u].suc[0]))
{
newNode(v, nd[v].w);
nd[v].pre = u;
nd[u].suc[0] = v;
splay(a, v);
}
else
_insert(a, nd[u].suc[0], v);
}
else
{
if(! (~ nd[u].suc[1]))
{
newNode(v, nd[v].w);
nd[v].pre = u;
nd[u].suc[1] = v;
splay(a, v);
}
else
_insert(a, nd[u].suc[1], v);
}
}

inline void insert(int a, int u)
{
_insert(a, rt[a], u);
}

void _merge(int a, int u)
{
int suc[2] = {nd[u].suc[0], nd[u].suc[1]};
insert(a, u);

for(int i = 0; i < 2; ++ i)
if(~ suc[i])
_merge(a, suc[i]);
}

inline int merge(int a, int b)
{
if(nd[rt[a]].sz < nd[rt[b]].sz)
std::swap(rt[a], rt[b]);

_merge(a, rt[b]);
}

int get(int u, int k)
{
if(~ nd[u].suc[0])
{
if(nd[nd[u].suc[0]].sz > k)
return get(nd[u].suc[0], k);
else
k -= nd[nd[u].suc[0]].sz;
}

if(! k)
return nd[u].w;

return get(nd[u].suc[1], k - 1);
}

inline int getMedian(int a)
{
return get(rt[a], nd[rt[a]].sz >> 1);
}
}trees;

int main()
{
#ifndef ONLINE_JUDGE
freopen("BZOJ1367.in", "r", stdin);
freopen("BZOJ1367.out", "w", stdout);
#endif

using namespace Zeonfai;

int n = getInt();

for(int i = 0; i < n; ++ i)
trees.newNode(i, a[i] = getInt() - i);

cnt = 0;

for(int i = 0; i < n; ++ i)
{
trees.rt[cnt] = i;
sec[cnt].w = a[i], sec[cnt].L = i, sec[cnt ++].R = i;

for(; cnt > 1 && sec[cnt - 2].w > sec[cnt - 1].w; -- cnt)
trees.merge(cnt - 2, cnt - 1), sec[cnt - 2].R = sec[cnt - 1].R, sec[cnt - 2].w = trees.getMedian(cnt - 2);
}

long long ans = 0;

for(int i = 0; i < cnt; ++ i)
for(int j = sec[i].L; j <= sec[i].R; ++ j)
ans += abs(a[j] - sec[i].w);

printf("%lld", ans);
}



posted @ 2017-05-20 16:02  Zeonfai  阅读(155)  评论(0编辑  收藏  举报