CodeForces 1136D - Nastya Is Buying Lunch (贪心)

博客围绕“传送门”题目展开,阐述解题思路。指出编号为 i 的同学与编号为 j 的同学交换位置的条件,从贪心角度考虑,先看离最后一位同学当前位置最近的人能否交换,能则计数加一,不能则用二元组更新未遍历位置,还提及实现过程较难理解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目: 传送门
思路:
    很明显,如果编号为 i 的同学要跟编号 为 j 的同学交换位置,他必须能跟它们之间所有的人都能交换,这样 i 同学才能到达j同学的前面相邻的位置,而这样对 j 同学的位置的贡献只是向前 +1 位.
    有了上述的结论,那么对于最后一个位置的同学也是如此,而且从贪心的角度来考虑,我们肯定先考虑离最后一位同学当前位置最近的人能不能交换,如果能就直接交换 ans++,如果不能,那么我们就通过所有以它结尾二元组更新之前还未遍历到的位置.
    注: 如果该位置能交换,我们就不能使用其二元组的贡献,因为能贡献它一定在 初始最后一个同学当先位置的后面。

    虽然思路不难,但是实现的过程有点难懂,大家且看且珍惜.

参考代码:

int n,m,ans;
int a[300050];
int cnt[300050];
vector<int> v[300050];

int main() {
    cin>>n>>m;
    for(int i=1;i<=n;i++) {
        cin>>a[i];
    }
    int x,y;
    for(int i=0;i<m;i++) {
        cin>>x>>y;
        v[y].push_back(x);
    }
    for(int i=0;i<v[a[n]].size();i++) {
        cnt[v[a[n]][i]]++;
    }
    for(int i=n-1;i>=1;i--) {
        if(n-i-ans == cnt[a[i]]) ans++;
        else {
            for(int j=0;j<v[a[i]].size();j++) {
                cnt[v[a[i]][j]]++;
            }
        }
    }
    cout<<ans<<endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值