[bzoj 1367][Baltic2004]sequence
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1367
[Baltic2004]sequence
Time Limit: 20 Sec Memory Limit: 64 MBSubmit: 1304 Solved: 531
[Submit][Status][Discuss]
Description
Input
Output
一个整数R
Sample Input
7
9
4
8
20
14
15
18
9
4
8
20
14
15
18
Sample Output
13
HINT
所求的Z序列为6,7,8,13,14,15,18.
R=13
对于严格递增的序列,只要选的和原来的数列一样就是最优的。
对于严格递减的序列,只有选时原来数列的中位数的数就是最优的(证明过程跟传递糖果差不多,就是转化成数轴上的最短距离和)
这样我们可以把数列化成部分递增,部分递减,分别贪心处理,当然这个过程中需要可并堆维护中位数。
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn = 1000005; 4 typedef long long ll; 5 int read(){ 6 int rt=0,fl=1;char ch=getchar(); 7 while(ch<'0'||ch>'9'){if(ch=='-')fl=-1;ch=getchar();} 8 while(ch>='0'&&ch<='9'){rt=rt*10+ch-'0';ch=getchar();} 9 return rt*fl; 10 } 11 ll ans; 12 int n,now; 13 int a[maxn],root[maxn]; 14 int L[maxn],R[maxn],tot[maxn]; 15 struct Tr{ 16 int cnt; 17 int l[maxn],r[maxn]; 18 ll v[maxn];int sz[maxn],d[maxn]; 19 int merge(int x,int y){ 20 if(x==0||y==0)return x+y; 21 if(v[x]<v[y])swap(x,y); 22 r[x]=merge(r[x],y); 23 sz[x]=sz[l[x]]+sz[r[x]]+1; 24 if(d[r[x]]>d[l[x]])swap(l[x],r[x]); 25 d[x]=d[r[x]]+1; 26 return x; 27 } 28 int top(int x){ 29 return v[x]; 30 } 31 int size(int x){ 32 return sz[x]; 33 } 34 void pop(int &x){ 35 x=merge(l[x],r[x]); 36 } 37 int Create(ll x){ 38 v[++cnt]=x; 39 sz[cnt]=1; 40 l[cnt]=r[cnt]=d[cnt]=0; 41 return cnt; 42 } 43 }heap; 44 int main(){ 45 n=read(); 46 for(int i=1;i<=n;i++)a[i]=read()-i; 47 for(int i=1;i<=n;i++){ 48 now++; 49 root[now]=heap.Create(a[i]); 50 tot[now]=1; 51 L[now]=R[now]=i; 52 while(now>1 && heap.top(root[now-1])>heap.top(root[now])){ 53 now--; 54 root[now]=heap.merge(root[now+1],root[now]); 55 tot[now]+=tot[now+1];R[now]=R[now+1]; 56 while(heap.size(root[now])*2>tot[now]+1) 57 heap.pop(root[now]); 58 } 59 } 60 for(int i=1;i<=now;i++) 61 for(int j=L[i],t=heap.top(root[i]);j<=R[i];j++) 62 ans+=abs(a[j]-t); 63 printf("%lld",ans); 64 }