BZOJ 1367: [Baltic2004]sequence
2015-05-11 19:01
411 查看
思考这道题目的时候毫无思路,而且数据范围很像是贪心题啊。其实我们可以考虑一些极端的情况,如何这个t序列就是递增的,那个直接zi=ti就好了,如果这个序列是递减的,我们可以让z序列全部等于t序列的中位数,这样显然是最优的。(证明略)但题目中z序列递增,所以做一个变换,让所有的zi-i,这样就保证递增了。接下来我们将递减序列进行合并,最后得到的就都是递增序列,直接赋值就好了,在将递减序列合并的时候,还要对应地合并这些序列的中位数,这项操作如何快速完成呢?想到利用可并堆(真不好想啊…),堆里存放的是这个序列前一半的元素,两个堆合并时保留合并的大序列的前一半元素,但这样好像并不一定得到中位数。比如将5 6 7 8 9和1 2 3 4合并,就得到1 2 5 6 7,但这样的情况并不会发生,因为我们每发现一个递减序列就合并, 很容易证得。
总结一下算法的过程,首先将输入序列进行变换,然后按顺序加入,如何发现存在两个序列的中位数递减,则可以进行合并,最后得到了递增的中位数序列,直接赋值相减。
Tips:absi2011的配对堆比我的左偏树高明得不知道到哪里去了。
#include<iostream> #include<algorithm> #include<cstring> #include<cstdio> using namespace std; const int maxn=1000000+10; int l[maxn],r[maxn],root[maxn],a[maxn],w[maxn],left1[maxn],right1[maxn],dis[maxn],v[maxn],n,tot; int num[maxn],cnt[maxn]; int merge(int x,int y) { if(!x||!y) return x+y; if(v[x]<v[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; } int top(int x) { return v[x]; } void pop(int &x) { x=merge(l[x],r[x]); } int main() { //freopen("1367.in","r",stdin); //freopen("1367.out","w",stdout); scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); a[i]-=i; } for(int i=1;i<=n;i++) { root[++tot]=i;v[i]=a[i];l[i]=r[i]=dis[i]=0; num[tot]=cnt[tot]=1;left1[tot]=i;right1[tot]=i; while(top(root[tot-1])>top(root[tot])&&tot>1) { tot--;root[tot]=merge(root[tot],root[tot+1]); num[tot]+=num[tot+1];cnt[tot]+=cnt[tot+1];right1[tot]=right1[tot+1]; while(cnt[tot]>(num[tot]+1)/2) { pop(root[tot]); cnt[tot]--; } } } long long ans=0; for(int i=1;i<=tot;i++) for(int j=left1[i];j<=right1[i];j++) ans+=abs(top(root[i])-a[j]); printf("%lld\n",ans); return 0; }
相关文章推荐
- 可并堆试水--BZOJ1367: [Baltic2004]sequence
- BZOJ 1367 [Baltic2004]sequence
- BZOJ 1367: [Baltic2004]sequence 左偏树
- 【BZOJ1367】[Baltic2004]sequence 左偏树
- 【bzoj1367】[Baltic2004]sequence
- 【bzoj1367】[Baltic2004]sequence 可并堆
- bzoj1367【Baltic2004】sequence
- 【BZOJ 1367】 1367: [Baltic2004]sequence (可并堆-左偏树)
- bzoj 1367: [Baltic2004]sequence
- BZOJ1367 [Baltic2004]sequence
- 【BZOJ】1367: [Baltic2004]sequence
- [BZOJ1367] [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】 [Baltic2004]sequence 可并堆
- BZOJ 1367([Baltic2004]sequence-左偏树+中位数贪心)