1 条题解
-
0
自动搬运
来自洛谷,原作者为

pandaSTT
Spores in the Wind.搬运于
2025-08-24 21:34:18,当前版本为作者最后更新于2021-12-18 18:50:26,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
前置知识
并查集
建议先完成这道题
分析
首先构造一组数据:
3 2 3 1我们发现如果想让整个序列升序排序,需要将当前 1 移动至当前 2 的位置,将当前 2 移动至当前 3 的位置,而当前 3 的位置需要移动至当前 1 的位置,也就是说,这些移动构成了一个环!
因此我们可以用并查集维护这样一个环,而最小代价则是处理每个环的最小代价之和。
对于每个环,我们需要维护 4 个值:
- 这个环的根节点
- 这个环中的最小值
- 这个环的权值之和
- 这个环的节点数量
对于每个环的最小代价,我们需要讨论两种情况:
1. 运用环内最小值进行交换
用 环内最小值交换节点数量减一次,再加上除这个环中的最小值之外其余节点的权值之和,就是这个环运用环内最小值进行交换的代价。
具体表示
(people[i]-1)*minn[i]+sum[i]-minn[i]2. 运用环外最小值进行交换
首先将环内最小值与环外最小值进行交换,再用 环外最小值交换节点数量减一次,再加上除这个环中的最小值之外其余节点的权值之和,最后将环内最小值与环外最小值进行交换回来,就是这个环运用环外最小值进行交换的代价。
具体表示
(people[i]-1)*mina+sum[i]-minn[i]+2*(mina+minn[i])代码
#include<bits/stdc++.h> #define int long long using namespace std; inline char gc(){ static char buf[1000010],*p1=buf,*p2=buf; return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000010,stdin),p1==p2)?EOF:*p1++; } inline int read(){ register int x=0,f=0; static char s=gc(); while(s<'0'||s>'9')f|=s=='-',s=gc(); while(s>='0'&&s<='9'){ x=(x<<3)+(x<<1)+(s^48);s=gc(); }return f?-x:x; } inline void write(register int x){ if(x<0)putchar('-'),x=-x; if(x>9)write(x/10);putchar(x%10^48); } int n,sum[1000005],minn[1000005],ans,father[1000005],people[1000005],mina=INT_MAX; struct nobe{ int id,val; friend bool operator<(nobe x,nobe y){ return x.val<y.val; } }a[1000005]; int findset(int x){ if(father[x]==x){ return x; } return father[x]=findset(father[x]); }//并查集寻找根节点操作 signed main(){ n=read(); for(int i=1;i<=n;i++){ a[i].val=read(); father[i]=a[i].id=i;//这个环的根节点 minn[i]=sum[i]=a[i].val;//这个环中的最小值,这个环的权值之和 people[i]=1;//这个环的节点数量 mina=min(mina,a[i].val);//环外最小值 } sort(a+1,a+n+1); for(int i=1;i<=n;i++){ if(a[i].id!=i){//若要构成环 int x=findset(a[i].id),y=findset(i); if(x!=y){ father[x]=y; sum[y]+=sum[x]; people[y]+=people[x]; minn[y]=min(minn[y],minn[x]);//并查集合并操作 } } } for(int i=1;i<=n;i++){ if(father[i]==i){ ans+=min((people[i]-1)*mina+sum[i]-minn[i]+2*(mina+minn[i]),(people[i]-1)*minn[i]+sum[i]-minn[i]); }//求每个环的最小代价 } write(ans); return 0; }总结
分析 难度 思维难度 紫 代码难度 绿 算法难度 橙 分析难度 蓝 综合评估 题外话
这道题作为我们模拟赛的 T2,在比赛中竟然没有人 AC ,这是多么恐怖!
这道题主要考察题目转化,代码实现与知识点考察并不难,偏向国外的思维题类型,而不像国内某些只会出数据结构。
(我没有针对 Ynoi)只要思维偏难,考试时就没人做对,可见我们的思维漏洞与国外的 OIer 还差距很远,我们更应该加强锻炼自己的思维,才能真正进步成一个好的 OIer!
- 1
信息
- ID
- 1113
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 5
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者