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\n",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("\n");
    }
    return 0;
}
posted @ 2021-03-24 21:55  EchoZQN  阅读(54)  评论(0编辑  收藏  举报