【NOIP2013】 火柴排队 贪心+splay
这题为啥我写得这么复杂。
首先我们不难发现,我们将序列a和序列b排序,考虑两序列内无相同元素,那么最小值显然为∑ni=1(ai−bi)2。
下面考虑做法
首先,我们将序列a和序列b离散化(以下提及序列a和b均为离散化后的数字)
然后,我们从前往后枚举序列a中的每一个数字,对于序列a中第i个数字ai,我们在序列b中找出数字ai的出现位置,并把它移动到序列b中第i个位置,与ai对齐。
对于序列b,我们用一个splay来维护,其中会出现插入和删除操作。
时间复杂度:O(nlogn)。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #include<set> 7 #include<map> 8 #include<queue> 9 #include<vector> 10 #define M 100005 11 #define L long long 12 #define MOD 99999997 13 #define lc(x) ch[x][0] 14 #define rc(x) ch[x][1] 15 using namespace std; 16 17 L ans=0,n,a[M]={0},b[M]={0},c[M]={0},wei[M]={0}; 18 L ch[M][2]={0},siz[M]={0},fa[M]={0},root=0; 19 20 void pushup(L x){siz[x]=siz[lc(x)]+siz[rc(x)]+1;} 21 void rotate(L x,L &k){ 22 L y=fa[x],z=fa[y]; 23 if(y==k) k=x; 24 else{ 25 if(lc(z)==y) lc(z)=x; 26 else rc(z)=x; 27 } 28 L l=(lc(y)!=x),r=l^1; 29 fa[y]=x; fa[x]=z; fa[ch[x][r]]=y; 30 ch[y][l]=ch[x][r]; ch[x][r]=y; 31 pushup(y); 32 pushup(x); 33 } 34 void splay(L x,L &k){ 35 while(x!=k){ 36 L y=fa[x],z=fa[y]; 37 if(y!=k){ 38 if((lc(z)==y)^(lc(y)==x)) rotate(x,k); 39 else rotate(y,k); 40 } 41 rotate(x,k); 42 } 43 } 44 45 void ins(L &x,L k,L id){ 46 if(!x) return void(x=id); 47 if(k<=siz[lc(x)]) ins(lc(x),k,id),fa[lc(x)]=x; 48 else ins(rc(x),k-siz[lc(x)]-1,id),fa[rc(x)]=x; 49 pushup(x); 50 } 51 void del(L id){ 52 splay(id,root); 53 L x=lc(id),y=rc(id); 54 siz[id]=1; fa[x]=fa[y]=0; 55 lc(id)=rc(id)=0; 56 if(!x) return void(root=y); 57 if(!y) return void(root=x); 58 root=x; 59 while(rc(x)) x=rc(x); 60 rc(x)=y; fa[y]=x; 61 splay(x,root); 62 } 63 64 signed main(){ 65 scanf("%d",&n); 66 for(L i=1;i<=n;i++) scanf("%lld",a+i),c[i]=a[i]; 67 sort(c+1,c+n+1); 68 for(L i=1;i<=n;i++) a[i]=lower_bound(c+1,c+n+1,a[i])-c; 69 for(L i=1;i<=n;i++) scanf("%lld",b+i),c[i]=b[i]; 70 sort(c+1,c+n+1); 71 for(L i=1;i<=n;i++) b[i]=lower_bound(c+1,c+n+1,b[i])-c; 72 for(L i=1;i<=n;i++) wei[b[i]]=i; 73 74 for(L i=1;i<=n;i++){ 75 siz[i]=1; 76 ins(root,i-1,i); 77 splay(i,root); 78 } 79 for(L i=1;i<=n;i++){ 80 int x=wei[a[i]]; 81 splay(x,root); 82 L nowid=siz[lc(x)]+1; 83 del(x); 84 ins(root,i-1,x); 85 splay(x,root); 86 ans+=abs(i-nowid); 87 } 88 cout<<ans%MOD<<endl; 89 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!