NOI.AC NOIP模拟赛 第一场 补记

NOIP模拟赛补记与算法解析
本文解析了NOIP模拟赛中的两道题目,包括糖果购买问题和序列排序问题。糖果购买问题通过排序和前缀和求解,序列排序问题采用归并排序和快速排序思想解决。

NOI.AC NOIP模拟赛 第一场 补记

candy

题目大意:

有两个超市,每个超市有\(n(n\le10^5)\)个糖,每个糖\(W\)元。每颗糖有一个愉悦度,其中,第一家商店中的第\(i\)颗糖果的愉悦度为\(A_i\),而第二家商店中的第\(i\)颗糖果的愉悦度为\(B_i\)

在每家商店买的糖果会被打包到一个袋子中(可以在一家商店什么都不买,此时认为这家商店的袋子为空)。因为这两个袋子外观是一样的,所以会从两个袋子中随机选择一个,然后吃光里面的糖果。定义一种买糖果的方案的愉悦度为:吃到的糖果的愉悦度之和的最小可能值。

求买糖果的愉悦度与买糖果的花费之差的最大值。

思路:

显然对于一家店,购买相同数量的糖果,一定选择愉悦度尽量高的更优。

因此将\(A_i\)\(B_i\)从大到小排序,求前缀和。答案就是\(\max\{\min(A_i,B_j)-(i+j)W\}\)。枚举每一个\(A_i,B_j\)作为\(\min\),然后另一个数就可以通过二分求出来。

时间复杂度\(\mathcal O(n\log n)\)

源代码:

#include<cstdio>
#include<cctype>
#include<algorithm>
inline int getint() {
    register char ch;
    while(!isdigit(ch=getchar()));
    register int x=ch^'0';
    while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    return x;
}
typedef long long int64;
const int N=1e5+1;
int64 a[N],b[N];
int main() {
    const int n=getint(),m=getint();
    for(register int i=1;i<=n;i++) a[i]=getint();
    for(register int i=1;i<=n;i++) b[i]=getint();
    std::reverse(&a[1],&a[n]+1);
    std::reverse(&b[1],&b[n]+1);
    for(register int i=1;i<=n;i++) a[i]+=a[i-1];
    for(register int i=1;i<=n;i++) b[i]+=b[i-1];
    int64 ans=0;
    for(register int i=0;i<=n;i++) {
        const int j=std::lower_bound(&b[0],&b[n]+1,a[i])-b;
        if(j<=n) ans=std::max(ans,a[i]-(int64)(i+j)*m);
    }
    for(register int i=0;i<=n;i++) {
        const int j=std::lower_bound(&a[0],&a[n]+1,b[i])-a;
        if(j<=n) ans=std::max(ans,b[i]-(int64)(i+j)*m);
    }
    printf("%lld\n",ans);
    return 0;
}

sort

来源:

Ufa SATU + Bucharest U Contest J. Reverse Sort

题目大意:

一个长度为\(n(n\le50000)\)的序列\(A\)。每次操作可以将一个区间翻转,定义翻转区间\([l,r]\)的代价为\(r-l+1\)。要通过翻转将这个序列排序,请你构造出代价小小于\(2\times10^7\)的一种方案。

思路:

\(A_i\in\{0,1\}\)时,用归并排序的思想,每次归并时将左子区间的后缀\(1\)与右子区间的前缀\(0\)交换即可。

而没有\(A_i\in\{0,1\}\)的条件时,我们可以利用快速排序的思想,每次从区间内随机选取一个数\(x\)作为基准,\(\le x\)的数作为\(0\)\(>x\)的数作为\(1\)。然后内层套用上述归并排序的算法。

源代码:

#include<cstdio>
#include<cctype>
#include<climits>
#include<algorithm>
inline int getint() {
    register char ch;
    while(!isdigit(ch=getchar()));
    register int x=ch^'0';
    while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    return x;
}
const int N=5e4+1;
int a[N];
inline bool check(const int &b,const int &e) {
    for(register int i=b;i<e;i++) {
        if(a[i]>a[i+1]) return false;
    }
    return true;
}
void solve(const int &b,const int &e,const int &x) {
    if(b==e) return;
    const int mid=(b+e)>>1;
    solve(b,mid,x);
    solve(mid+1,e,x);
    int p=b,q=e;
    while(p<=mid&&a[p]<=x) p++;
    while(q>mid&&a[q]>x) q--;
    if(p<=mid&&q>mid) {
        printf("%d %d\n",p,q);
        std::reverse(&a[p],&a[q]+1);
    }
}
void solve(const int &b,const int &e) {
    if(b>=e) return;
    if(check(b,e)) return;
    const int x=a[b+rand()%(e-b+1)];
    solve(b,e,x);
    for(register int i=b;i<=e;i++) {
        if(a[i]>x) {
            solve(b,i-1);
            solve(i,e);
            return;
        }
    }
    solve(b,e);
}
int main() {
    srand(998244353);
    const int n=getint();
    for(register int i=1;i<=n;i++) a[i]=getint();
    solve(1,n);
    puts("-1 -1");
    return 0;
}

转载于:https://www.cnblogs.com/skylee03/p/9686093.html

内容概要:本文系统介绍了算术优化算法(AOA)的基本原理、核心思想及Python实现方法,并通过图像分割的实际案例展示了其应用价值。AOA是一种基于种群的元启发式算法,其核心思想来源于四则运算,利用乘除运算进行全局勘探,加减运算进行局部开发,通过数学优化器加速函数(MOA)和数学优化概率(MOP)动态控制搜索过程,在全局探索与局部开发之间实现平衡。文章详细解析了算法的初始化、勘探与开发阶段的更新策略,并提供了完整的Python代码实现,结合Rastrigin函数进行测试验证。进一步地,以Flask框架搭建前后端分离系统,将AOA应用于图像分割任务,展示了其在实际工程中的可行性与高效性。最后,通过收敛速度、寻优精度等指标评估算法性能,并提出自适应参数调整、模型优化和并行计算等改进策略。; 适合人群:具备一定Python编程基础和优化算法基础知识的高校学生、科研人员及工程技术人员,尤其适合从事人工智能、图像处理、智能优化等领域的从业者;; 使用场景及目标:①理解元启发式算法的设计思想与实现机制;②掌握AOA在函数优化、图像分割等实际问题中的建模与求解方法;③学习如何将优化算法集成到Web系统中实现工程化应用;④为算法性能评估与改进提供实践参考; 阅读建议:建议读者结合代码逐行调试,深入理解算法流程中MOA与MOP的作用机制,尝试在不同测试函数上运行算法以观察性能差异,并可进一步扩展图像分割模块,引入更复杂的预处理或后处理技术以提升分割效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值