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); }
练习:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
2022-07-21 C05【模板】FHQ Treap P3369 普通平衡树