Codeforces Round #709 (Div. 2)D.Playlist(思维)
题意:
从1到n反复循环,每次走两步,若当前走的第一步与第二步互质,则删除第二步的位置的元素。最后输出依次删除的元素的位置。
思路:
用队列模拟,先把所以元素放进去,每次取出头做第一步,若第二步的位置与其互质,则标记第二步的位置,以后不再走,并把当前元素重新放进队列
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll,ll>pii;
const ll inf=1e15;
const int maxn=1e5+5;
int t,n,m,nex[maxn],a[maxn],ans[maxn],k,vis[maxn];
inline int gcd(int a,int b) {
int r;
while(b>0) {
r=a%b;
a=b;
b=r;
}
return a;
}
queue<int>p;
int main(){
scanf("%d",&t);
while(t--){
k=0;
while(!p.empty())p.pop();
memset(nex,0,sizeof(nex));
memset(vis,0,sizeof(vis));
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
nex[i]=i+1;
p.push(i);
}
nex[n]=1;
while(!p.empty()){
int x=p.front(),y=nex[x];
p.pop();
if(!vis[x]&&gcd(a[x],a[y])==1){
vis[y]=1;
ans[++k]=y;
nex[x]=nex[y];
p.push(x);
}
}
printf("%d",k);
for(int i=1;i<=k;i++)
printf(" %d",ans[i]);
printf("\n");
}
}
(好巧妙啊,堆模拟,线性做法)