Codeforces 1340A Nastya and Strange Generator(思维)

题目链接

题目大意

  题目给出了一个序列,每个数字对应的位置就是第几步选择的位置。比如2 3 4 5 1,就是说第一步选了第5个位置,第二步选了第1个位置,第三步选了第3个位置。
  位置选择的限制由两个数组决定,一个是(r)数组,一个是(count)数组。你可以假设原来有一个数组(a)里面的数是1,2,3...n,(r)数组代表的就是从当前这个数开始(包括自己)向右数,数组(a)中还没有被选择的第一个数,没有就是×,而(count)数组计算的是(r)数组中每个数出现的次数,每次都必须选一个(count)数组里最大的数所在位置,如果有多个可以任选一个。显然,按照上面的方法,一开始的(r)数组和(a)数组相同,为1,2,3...n,(count)里面都是(1)
  对第一个样例的解释再做一下解释。

  第一步因为还没有数字被选,所以(r)里面有所有的数字,(count)里面都是(1),所以可以随便选,我们的样例是2 3 4 5 1,也就是说第一步选了第(5)个位置,于是(5)被拿走了,(count[5])变成0。
  第二步因为最大的(5)被拿走了,所以第(5)个位置右边已经没有数了,所以(r)数组第(5)个数是×,因为其他位置上的数(count)(1),所以可以在(1~4)里选,根据样例,第二步选了第(1)个位置,于是(1)被拿走了,(count[1])变为(0)
  第三步因为(1)被拿走了,所以(r)数组的第一位向右找第一个没被选的数是(2)(r[1])就变成了(2)(count[2])变成了(2)。显然现在(count[2])是最大的,所以需要拿走(2),而样例是2 3 4 5 1,第三步正好是拿走第(2)个位置,所以没问题,下面几步也和这步类似。

再来看一个不太行的栗子

  我们来看1 3 2这个样例((a)数组是我假设出来的,方便理解)。
  起初我们有(a = [1,2,3], r = [1,2,3], count = [1,1,1])。因为(count)里面都是(1),换句话说每个数都是出现次数最多的数,所以可以随便选,因为样例的(1)在第(1)个位置,所以第一步选(1)
  第一步之后,(a = [2,2,x], r = [2,2,3], count = [0,2,1])。这时候(2)的出现次数最多的,出现了(2)次,所以第二步只能选(2),但是样例里的(2)在第(3)个位置,也就是选了(3),这是矛盾的,所以这个样例不行。

具体实现

  这题本质上就是一道阅读理解题,题中给的信息就是用来迷惑你的,从样例里面可以看出,每次都选末尾剩下来的最大的数,那么对于剩下来的数来说可以随便选,它们的(count)值不会改变,如果从它们中间或者最前面开始选,就只能从头选到不能选为止(因为它后一个数的(count)值会不断递增,总是会成为最大的数)。两种情况实际上本质都是选一个数字,然后往后选,选到不能选(后面的数没有/已经被选走)为止,所以我们只要检查一下给出的序列是否符合这个顺序就是了。

const int maxn = 2e5+10;
int pos[maxn]; bool vis[maxn];
int main(void) {
    int t;
    cin >> t;
    while(t--) {
        int n;
        cin >> n;
        for (int i = 1, num; i<=n; ++i) {
            cin >> num;
            pos[num] = i; vis[i] = true; //记录每一步选的位置
        }
        bool ok = true;
        for (int i = 1; i<=n; ++i) {
            if (!vis[pos[i]]) ok = false;
            else {
                int tmp = pos[i];
                vis[tmp] = false;
                while(vis[tmp+1]&&i<n) { //往后一直选到不能选
                    vis[++tmp]=false;
                    if (pos[++i]!=tmp) ok = false; //判断结果和给出的序列是否相等
                }
            }
        }
        for (int i = 1; i<=n; ++i) pos[i] = vis[i] = 0;
        cout << (ok ? "Yes
" : "No
");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/shuitiangong/p/12777894.html