Luogu P11158 【MX-X6-T4】夢重力 题解
分类讨论好题。
不难发现交换行等价于交换列,考虑转化贡献体,枚举长度为 区间,统计这个区间被多少种交换方式包含。
考虑一个长度为 区间满足要求的充要条件是存在一段空权值区间 使得区间中所有 不属于 。注意到如果存在满足要求的区间则其余每一行都必然有数,且上边界必然在 ,下边界必然在 ,所以我们维护 中的最大值和 中的最小值即可判定是否存在满足要求的区间。可以使用 set
维护。
如果这个区间本身就满足要求,那么在区间内部交换或区间外部交换没有影响,对答案贡献 。但是如果 中有数,我们可以把 中的最大值换成一个较小的上边界,同样满足条件。如果 中有数同理。需要特判一下。
如果这个区间本身不满足要求,还是有可能通过交换得到满足要求的区间。不难发现此时一定是换掉 中的最大值或 中的最小值,于是我们分别计算一下换掉之后的区间大小即可。注意如果换掉之后空权值区间长度大于 ,则有两种换法,如果空权值区间长度等于 ,则只有一种换法。这个结论手玩一下不难发现。
然后就做完了,时间复杂度 。
#include <bits/stdc++.h>
using namespace std;
long long n,a[500000],cs=0,cb=0,ans=0;
set<long long>q;
int main()
{
scanf("%lld",&n);
for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
q.insert(0),q.insert(n+1);
for(int i=1;i<=n/2;i++)q.insert(a[i]);
for(int i=1;i<=n/2+1;i++)
{
set<long long>::iterator mx=q.lower_bound(n/2+1),mi=q.upper_bound(n/2),tmp=mx;
mi--;
if((*mx)-(*mi)-1>=n/2)
{
ans+=(n/2)*(n/2-1);
if((*mx)!=n+1)ans++;
if((*mi)!=0)ans++;
}
else
{
mx++;
if((*mx)-(*mi)-1>n/2)ans+=2;
else if((*mx)-(*mi)-1==n/2)ans++;
mx=tmp,mi--;
if((*mx)-(*mi)-1>n/2)ans+=2;
else if((*mx)-(*mi)-1==n/2)ans++;
}
q.insert(a[i+n/2]),q.erase(a[i]);
}
printf("%lld\n",ans);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探