【可并堆】BZOJ1367(Baltic2004)[sequence]题解
2018-01-08 11:46
405 查看
题目概述
给出 {an} ,选择一个上升序列 {bn} 使得 ∑ni=1|ai−bi| 最小,求最小值。解题报告
对于这道题,我们可以将 {an} 改成 {an−n} ,然后就转化为求不下降序列 {bn} 。如果 {an} 递减,那么 {bn} 显然取中位数最好。如果不递增,我们可以把序列划为若干段,每个段都取该段中位数(中位数不下降)。可以证明最优的 {bn} 一定是这样的形式。
对于 i ,我们先将其单独成段,然后检查前一段的中位数是不是 ≤ai ,如果不是,那么就把两段合并,求出新的中位数,直到满足。由此可见我们需要能快速求中位数,快速合并的数据结构来维护。由于前一段的中位数 ≤ai ,所以新的中位数不会比 ai 小,那么我们就可以用可并堆,只需要维护 si≤⌊num2⌋+1 ,堆顶就是中位数。
示例程序
#include<cstdio> #include<cctype> #include<algorithm> typedef long long LL; using namespace std; const int maxn=1e6; int n,v[maxn+5],ro[maxn+5],son[maxn+5][2],dis[maxn+5]; int tot,L[maxn+5],R[maxn+5],si[maxn+5];LL ans; #define Eoln(x) ((x)==10||(x)==13||(x)==EOF) inline char readc(){ static char buf[100000],*l=buf,*r=buf; if (l==r) r=(l=buf)+fread(buf,1,100000,stdin); if (l==r) return EOF;return *l++; } inline int readi(int &x){ int tot=0,f=1;char ch=readc(),lst='+'; while (!isdigit(ch)) {if (ch==EOF) return EOF;lst=ch;ch=readc();} if (lst=='-') f=-f; while (isdigit(ch)) tot=(tot<<3)+(tot<<1)+ch-48,ch=readc(); return x=tot*f,Eoln(ch); } int Merge(int a,int b){ if (!a||!b) return a+b;if (v[a]<v[b]) swap(a,b); int &l=son[a][0],&r=son[a][1]; r=Merge(r,b);if (dis[l]<dis[r]) swap(l,r); return dis[a]=dis[r]+1,a; } #define Pop(ID) ro[ID]=Merge(son[ro[ID]][0],son[ro[ID]][1]),si[ID]-- inline int absi(int x) {if (x<0) return -x;return x;} int main(){ freopen("program.in","r",stdin); freopen("program.out","w",stdout); readi(n);dis[0]=-1;for (int i=1;i<=n;i++) readi(v[i]),v[i]-=i; for (int i=1;i<=n;i++){ ro[++tot]=i;L[tot]=i;R[tot]=i;si[tot]=1; while (tot>1&&v[ro[tot-1]]>v[ro[tot]]){ tot--;ro[tot]=Merge(ro[tot],ro[tot+1]); R[tot]=R[tot+1];si[tot]+=si[tot+1]; while (si[tot]>(R[tot]-L[tot]>>1)+1) Pop(tot); } } for (int t=1;t<=tot;t++) for (int i=L[t];i<=R[t];i++) ans+=absi(v[i]-v[ro[t]]); return printf("%lld\n",ans),0; }
相关文章推荐
- bzoj1367【Baltic2004】sequence
- BZOJ 1367 [Baltic2004]sequence 解题报告
- BZOJ 1367: [Baltic2004]sequence [可并堆 中位数]
- BZOJ 1367 [Baltic2004]sequence【脑洞+可并堆
- BZOJ 1367 [Baltic2004]sequence
- 可并堆试水--BZOJ1367: [Baltic2004]sequence
- BZOJ_1367_[Baltic2004]sequence_结论题+可并堆
- BZOJ1367 [Baltic2004]sequence 【左偏树】
- bzoj 1367: [Baltic2004]sequence 左偏树+贪心
- BZOJ1367 [Baltic2004]sequence
- BZOJ 1367: [Baltic2004]sequence 左偏树
- BZOJ[1367][Baltic2004]Sequence 可并堆
- BZOJ 1367: [Baltic2004]sequence
- 【BZOJ】1367: [Baltic2004]sequence
- BZOJ 1367([Baltic2004]sequence-左偏树+中位数贪心)
- 【BZOJ 1367】 1367: [Baltic2004]sequence (可并堆-左偏树)
- [BZOJ1367] [Baltic2004]sequence
- 【左偏树+贪心】BZOJ1367-[Baltic2004]sequence
- bzoj 1367: [Baltic2004]sequence
- [可并堆 中位数] BZOJ 1367 [Baltic2004]sequence