牛客周赛 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;
}

浙公网安备 33010602011771号