[BZOJ1367] [Baltic2004]sequence
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
试题分析
因为绝对值符号一般涉及到中位数的介入,所以我们先将(a_i=a_i-i),这样可以将(b_i<b_{i+1})转化成(b_ileq b_{i+1})
当(a_1leq a_2leq ldotsleq a_n)的时候,显然取(b_i =a_i)最优。
当(a_1>a_2>ldots>a_n)的时候,取中位数最优。
我们先将这个最优的解大致构造出来再考虑调整。
显然当取(b_i=a_i)最优,那么如果存在(b_i>b_{i+1})怎么办呢?
根据上面的推论,由于一段数最优的是中位数,所以只会把(b_i)和(b_{i+1})这两段合并。
那么我们用可并堆维护合并的中位数即可。
BZOJ空间太小了吧
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define LL long long
inline LL read(){
LL x=0,f=1; char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=getchar()) x=x*10+c-'0';
return x*f;
}
const LL INF = 2147483600;
const LL MAXN = 1100000;
int N; int t[MAXN+1];
struct Heap{
int l[MAXN+1],r[MAXN+1]; int val[MAXN+1],sz[MAXN+1];
int rt[MAXN+2],dis[MAXN+1]; int cnt; bool c;
inline LL merge(LL x,LL y){
if(!x||!y) return x|y;
if(c^(val[x]<val[y])) swap(x,y);
r[x]=merge(r[x],y);
if(dis[l[x]]<dis[r[x]]) swap(l[x],r[x]);
dis[x]=dis[r[x]]+1; return x;
}
inline void pop(LL x){
rt[x]=merge(l[rt[x]],r[rt[x]]); sz[x]--; return ;
}
inline void insert(LL x,LL y){
rt[N+1]=++cnt; l[cnt]=r[cnt]=0; val[cnt]=y;
rt[x]=merge(rt[x],rt[N+1]); sz[x]++; return ;
}
}mx,mi;
inline LL Get(LL x){
if(!x) return 0;
while(mx.sz[x]<mi.sz[x]){
LL v=mi.val[mi.rt[x]];
mi.pop(x); mx.insert(x,v);
}
while(mx.sz[x]-mi.sz[x]>1){
LL v=mx.val[mx.rt[x]];
mx.pop(x); mi.insert(x,v);
}
if(!mi.sz[x]) return mx.val[mx.rt[x]];
return mx.val[mx.rt[x]];
} int las[MAXN+1],L[MAXN+1],R[MAXN+1];
int main(){
N=read(); mx.c=0; mi.c=1;
for(LL i=1;i<=N;i++){
t[i]=read(),t[i]-=i;
} LL cnt=0,Las=0;
for(LL i=1;i<=N;i++){
++cnt; mx.insert(cnt,t[i]); las[cnt]=Las;
L[cnt]=i;
R[cnt]=i; Las=cnt; LL cntx=cnt;
while(cntx&&Get(cntx)<Get(las[cntx])){
mx.sz[las[cntx]]+=mx.sz[cntx];
mx.merge(mx.rt[las[cntx]],mx.rt[cntx]);
mi.sz[las[cntx]]+=mi.sz[cntx];
mi.merge(mi.rt[las[cntx]],mi.rt[cntx]);
Get(las[cntx]);
R[las[cntx]]=R[cntx]; Las=las[cntx]; cntx=las[cntx];
}
} LL ans=0;
for(LL i=Las;i;i=las[i]){
LL mid=Get(i);
for(LL j=L[i];j<=R[i];j++)
ans+=max(t[j]-mid,mid-t[j]);
} printf("%lld
",ans);
return 0;
}