CF1295E Permutation Separation
本文版权归博客园,洛谷博客和蒟蒻wjr所有,欢迎转载,但需保留此段声明,并给出原文链接,如有侵权行为,还请不吝啬向博主举报,谢谢合作。
开一波E题闷声发大财
感谢@Karry5307 在考后提供思路
给定一个序列(为1~n的排列),和这个序列每一个数所对应的花费a以及序列的长度n。
取一数,将序列分成两个序列,分别是和
将两个序列的某些数移到另一个序列使得第一个序列的所有数小于第二个序列的所有数,注意如果其中一组为空,则满足此条件,移动的花费是
求最小花费
一道裸的线段树
考虑维护的前缀和,因为,所以前缀和最多只要维护到即可
假设第一个序列的所有数都移到了第二个序列值最小虽然不大可能则
答案是中的最小值
因为序列是1~n的排列,所以记为在序列中出现的位置
枚举i从1~n
假设将最终在第一序列,那么,考虑当前对前缀和的修改。
当时,在第一序列,那么不需要费用
当时,在第二序列,需要的费用移动到第一序列
则将~的值分别加上
~的值分别减去
当前策略最小值即当前的最小值。
答案即是对所有策略的最小值取最小值
#include <cstdio>
#include <algorithm>
#define re register
#define ll long long
#define lc (root<<1)
#define rc (root<<1|1)
using namespace std;
template<typename T>
inline void read(T&x)
{
x=0;
char s=(char)getchar();
bool flag=false;
while(!(s>='0'&&s<='9'))
{
if(s=='-')
flag=true;
s=(char)getchar();
}
while(s>='0'&&s<='9')
{
x=(x<<1)+(x<<3)+s-'0';
s=(char)getchar();
}
if(flag)
x=(~x)+1;
return;
}
const int N=2e5+5;
struct Tree
{
ll minn,lazy;
} tree[N<<2];
ll sum[N];
inline void build(int root,int l,int r)
{
if(l==r)
{
tree[root].minn=sum[l];
tree[root].lazy=0;
return;
}
int mid=(l+r)>>1;
build(lc,l,mid);
build(rc,mid+1,r);
tree[root].minn=min(tree[lc].minn,tree[rc].minn);
return;
}
inline void pushdown(int root)
{
if(!tree[root].lazy)
return;
tree[lc].minn+=tree[root].lazy;
tree[rc].minn+=tree[root].lazy;
tree[lc].lazy+=tree[root].lazy;
tree[rc].lazy+=tree[root].lazy;
tree[root].lazy=0;
return;
}
inline void change(int root,int l,int r,int x,int y,int val)
{
if(r<x||l>y)
return;
if(x<=l&&r<=y)
{
tree[root].minn+=val;
tree[root].lazy+=val;
return;
}
int mid=(l+r)>>1;
pushdown(root);
change(lc,l,mid,x,y,val);
change(rc,mid+1,r,x,y,val);
tree[root].minn=min(tree[lc].minn,tree[rc].minn);
return;
}
int n,p[N],a[N],pos[N];
ll ans;
int main()
{
read(n);
for(re int i=1; i<=n; ++i)
{
read(p[i]);
pos[p[i]]=i;
}
for(re int i=1; i<=n; ++i)
{
read(a[i]);
sum[i]=sum[i-1]+a[i];
}
build(1,1,n-1);
ans=tree[1].minn;
for(re int i=1; i<=n; ++i)
{
change(1,1,n-1,1,pos[i]-1,a[pos[i]]);
change(1,1,n-1,pos[i],n-1,-a[pos[i]]);
// printf("%d\n",ans);
ans=min(ans,tree[1].minn);
}
printf("%lld\n",ans);
return 0;
}
作者:蒟蒻wjr
欢迎任何形式的转载,但请务必注明出处。
限于本人水平,如果文章和代码有表述不当之处,还请不吝赐教。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?