牛客周赛 round99 E题 小宇

题目链接:https://ac.nowcoder.com/acm/contest/112544/E

思路

首先输入每个数字时候判断一遍该数字与下标大小关系,如果小于下标说明说,因为最小情况严格单调递增情况下,是所有数字都对应下标,而这个数字甚至小于下标,所以说,这个数字一定需要进行一次改变,那么设定一个set记录修改过的数字,以便后续对同样数字进行处理修改为下标数字处理。

接着设定l表示判断的左边界,这个边界表示1~l的数字都已经排好数字了。每次循环都对标记过的数字进行及时修改。接着从后往前遍历,获取第一个需要修改的下标,如果说l-1与i相等说明,完整的进行了一次区间的判断,说明区间数字都没问题,这时候就直接break退出循环,否则就将l与此时i区间的数字进行判断修改,如果数字不等于下标就进行修改,后续因为可能出现大数字修改为下标数字改变了单调性的情况,所以需要不断while循环,直到完整结束

题解

#include <bits/stdc++.h>
using namespace std;
const int N=2e5+10;
typedef long long ll;
int t,n;
int a[N];
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin>>t;
    while(t--)
    {
        int i;
        cin>>n;
        set<int>s;
        for(i=1;i<=n;i++)
        {
            cin>>a[i];
            if(a[i]<i)s.insert(a[i]),a[i]=i;
        }
        int l = 1;
        while(1)
        {
            for(i=l;i<=n;i++)
            {
                if(s.count(a[i]))
                {
                    a[i]=i;
                }

            }
            for(i=n-1;i>=l;i--)
            {
                if(a[i]>=a[i+1])break;
            }
            if(i<l)break;
            for(int j=l;j<=i;j++)
            {
                if(a[j]!=j)s.insert(a[j]);
            }
            l=i+1;
        }
        cout<<s.size()<<endl;
    }
    return 0;
}


posted @ 2025-07-08 17:27  屈臣  阅读(18)  评论(0)    收藏  举报