Luogu P10843 Turtle and Cycles 题解 [ 蓝 ] [ 差分 ] [ 前缀和 ] [ 贪心 ] [ 数学 ]
Turtle and Cycles:修改转化为交换差分数组的 trick 运用。这个 trick 实际上在 NOIp2021 里出过一次了。
转化
首先,
修改后,
设
那么我们要让这个环满足条件,首先就得破环为链。拆成链之后,显然只能有一个地方满足
贪心
接下来考虑如何最小化操作次数,不难发现,贪心移动时,对于在中间点左边的
假设我们当前计算的区间为
先考虑左半边的情况,设
但是实际有些
左半边的答案就是
右半边同理,就不写了。
时间复杂度
代码
#include <bits/stdc++.h>
#define fi first
#define se second
#define lc (p<<1)
#define rc ((p<<1)|1)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pi;
int t,n,a[400005];
ll g[400005],f[400005],sg[400005];
bitset<400005>b;
ll cal()
{
ll ans=0x3f3f3f3f3f3f3f3f;
for(ll i=1;i<=n;i++)
{
int mid=i+n/2-1;
ll lk=f[mid]-f[i-1];
ll lres=g[mid]-g[i-1]-lk*i-(lk-1)*lk/2;
ll rk=f[i+n-1]-f[mid];
ll rres=sg[mid+1]-sg[i+n]-rk*(2*n-(i+n-1)+1)-(rk-1)*rk/2;
ans=min(ans,lres+rres);
}
return ans;
}
void solve()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
a[i+n]=a[i];
}
for(int i=2;i<=n+1;i++)
{
b[i-1]=(a[i]>a[i-1]);
b[i-1+n]=b[i-1];
}
for(int i=1;i<=2*n;i++)
{
f[i]=f[i-1]+b[i];
g[i]=g[i-1]+i*b[i];
}
sg[2*n+1]=0;
for(int j=1,i=2*n;i>=1;i--,j++)sg[i]=sg[i+1]+j*b[i];
cout<<cal()<<'\n';
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>t;
while(t--)solve();
return 0;
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战