C18 左偏树 P4331 [BalticOI 2004] 数字序列

视频链接:238 左偏树 数字序列_哔哩哔哩_bilibili

Luogu P4331 [BalticOI 2004] Sequence 数字序列

 

 

 

Luogu P4331 [BalticOI 2004] Sequence 数字序列

复制代码
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

const int N=1000010;
int n,top;
struct segment{ //段的信息
  int rt;  //中位数
  int r;   //段的右端
  int siz; //剩余元素的个数
}s[N];
int lc[N],rc[N],dis[N],a[N],b[N]; //左偏树

int merge(int x,int y){ //合并堆
  if(!x || !y) return x+y;
  if(a[x]<a[y]) swap(x,y); //大根堆
  rc[x]=merge(rc[x],y);
  
  if(dis[lc[x]]<dis[rc[x]]) swap(lc[x],rc[x]);
  dis[x]=dis[rc[x]]+1;
  return x; //返回合并堆的根
}
int del(int x){ //删除堆顶
  return merge(lc[x],rc[x]);
}
int main(){
  scanf("%d",&n); dis[0]=-1;
  for(int i=1;i<=n;i++)
    scanf("%d",&a[i]), a[i]-=i; //转换求不降序列
  for(int i=1;i<=n;i++){
    s[++top]=(segment){i,i,1}; //每个数看做一段
    while(top>1 && a[s[top-1].rt]>a[s[top].rt]){
      s[top-1].rt=merge(s[top-1].rt, s[top].rt);
      s[top-1].r=s[top].r; 
      s[top-1].siz+=s[top].siz;
      top--;
      while(s[top].siz>(s[top].r-s[top-1].r)/2+1){
        s[top].rt=del(s[top].rt);
        s[top].siz--;
      }
    }
  }
  for(int i=1,j=1; i<=top; i++)
    while(j<=s[i].r) b[j++]=a[s[i].rt];
  long long res=0;
  for(int i=1; i<=n; i++) res+=abs(a[i]-b[i]);
  printf("%lld\n",res);
  for(int i=1; i<=n; i++) printf("%d ",b[i]+i);
}
复制代码

 

练习:

Luogu P3642 [APIO2016] 烟火表演

POJ3016 K-Monotonic

Luogu P4359 [CQOI2016] 伪光滑数

Luogu P8950 [YsOI2022] 道路修建

 

posted @   董晓  阅读(164)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
历史上的今天:
2022-07-21 C05【模板】FHQ Treap P3369 普通平衡树
点击右上角即可分享
微信分享提示