• D. Playlist 思维


    D. Playlist 思维

    题目大意:

    Arkady的播放列表最初包含 (n) 首歌曲,按照它们在播放列表中出现的顺序从 1到 (n) 编号。 Arkady从歌曲1开始开始逐一收听播放列表中的歌曲。播放列表循环播放,听完最后一首歌后,Arkady将从头开始继续听。

    每首歌曲都有一个类型 (a_i),它是一个正整数。让Arkady完成听一首类型为 (y) 的歌曲,倒数第二首听过的歌曲的类型为 (x)。如果gcd(x,y)= 1,则从播放列表中删除最后收听的歌曲(类型y)。之后,他将继续正常收听,跳过已删除的歌曲并忘记他之前听过的歌曲。换句话说,删除歌曲后,他不能立即删除下一首歌曲。

    比如:最开始是的列表是 ([5,9,2,10,15])

    • 因为 (gcd(5,9)=1) 所以,删掉9,就变成 ([5,2,10,15])
    • 虽然现在 (gcd(5,2)=1) 但是不会继续删掉 2,而是会去比较 (gcd(2,10)) 因为不是等于1,所以不会删掉10
    • 继续比较 (gcd(10,15)) 也不会删掉
    • 然后比较 (gcd(15,5)) 也不会删
    • 然后比较 (gcd(5,2)) 因为等于1 ,所以删掉2
    • 最后一致循环都不会删掉任意一个值,所以最后的序列是 ([5,10,15])

    题解:

    挺思维的。

    • 首先发现进行一轮之后,下一轮需要判断的点,只有之前进行比较 (gcd(x,y)=1)(x)(y) 被删掉了)
    • 所以只要把之前的 (x) 按照顺序放入一个队列中即可。
    • 这个还有一个删的操作,这个只要把下一个位置用一个数组存下来即可。
    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 2e5+10;
    typedef long long ll;
    int to[maxn],a[maxn],vis[maxn];
    queue<int>que;
    vector<int>ans;
    void init(int n){
        ans.clear();
        while(!que.empty()) que.pop();
        for(int i=0;i<n;i++) to[i] = (i+1)%n,vis[i] = 0;
    }
    int gcd(int a,int b){
        return b==0?a:gcd(b,a%b);
    }
    void debug(int n){
        for(int i=0;i<n;i++) printf("to[%d]=%d  ",i,to[i]);
    }
    int main(){
        int t;
        scanf("%d",&t);
        while(t--){
            int n;
            scanf("%d",&n);
            init(n);
            for(int i=0;i<n;i++) scanf("%d",&a[i]);
            int id = -1;
            for(int i=0;i<=n;i++){
                if(id==-1) id = i;
                else {
                    int v = i%n,now = gcd(a[id],a[v]);
                    if(now==1) {
                        vis[v] = 1;
                        ans.push_back(v+1),que.push(id);
                        to[id] = to[v],id = -1;
                    }
                    else id = i;
                }
            }
            while(!que.empty()){
                int u = que.front();que.pop();
                if(vis[u]) continue;
                int v = to[u],now = gcd(a[u],a[v]);
    //            printf("u = %d v = %d
    ",u,v);
    //            debug(n);
                if(now==1){
                    vis[v] = 1;
                    ans.push_back(v+1),que.push(u);
                    to[u] = to[v];
                }
            }
            printf("%d",ans.size());
            for(int i=0;i<ans.size();i++){
                printf(" %d",ans[i]);
            }
            printf("
    ");
        }
        return 0;
    }
    
  • 相关阅读:
    【嵌入式】arm-linux-gcc/ld/objcopy/objdump参数概述
    【Java】Java复习笔记-第四部分
    【C/C++】C语言复习笔记-17种小算法-解决实际问题
    【Java】Java复习笔记-三大排序算法,堆栈队列,生成无重复的随机数列
    【Java】Java复习笔记-第三部分
    【教程】ubuntu下安装NFS服务器
    【Java】Java复习笔记-第二部分
    【Java】Java复习笔记-第一部分
    【教程】ubuntu下安装samba服务器
    【C/C++】一道试题,深入理解数组和指针
  • 原文地址:https://www.cnblogs.com/EchoZQN/p/14575320.html
Copyright © 2020-2023  润新知