Codeforces 709 div2 DPlaylist 双端队列+链表

链接:https://codeforces.com/contest/1484/problem/D

题意
给你一个数组,每次找到一对互质的数时,删去其中第二个,不能连续删除,求最终删除的顺序。

思路
按照题目模拟就好了,需要用数据结构优化。

每次取出队首的数,判断是否和它的下一位互质,如果是的话将下一位删去,用数组模拟链表,就只需要将nex[x]指向nex[nex[x]],再将队首的数放回队尾。直到队列为空。

这个题一开始我只用了双端队列来写,按上述思路模拟,也是对的,不过最后一个点会超时。就很神奇,加了一个链表就过了,感觉好像是差不多的思路。

代码

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
#define  PII pair<int,int>
deque<int> q;
vector<int> ans;

int nex[maxn],a[maxn],vis[maxn];
int gcd(int a,int b){
    return b == 0 ? a:gcd(b,a % b);
}


int main()
{
    ios::sync_with_stdio(false);
    int t,n,j,cnt,pos;
    PII x1,x2;
    cin>>t;
    while(t--){
        cnt  = 0;
        q.clear();
        ans.clear();
        cin>>n;
        for(int i = 1;i <= n; i++){
            cin>>j;
            a[i] = j;
            nex[i - 1] = i;
            q.push_back(i);
            vis[i] = 0;
        }
        nex[n] = 1;
        while(!q.empty()){
            int x = q.front();q.pop_front();
            // cout<<x<<endl;
            if(vis[x])
                continue;
            if(gcd(a[x],a[nex[x]]) == 1){
                ans.push_back(nex[x]);
                vis[nex[x]] = 1;
                nex[x] = nex[nex[x]];
                q.push_back(x);
            }
        }
        cout<<ans.size()<<" ";
        for(auto i : ans)
            cout<<i <<" ";
        cout<<endl;
    }

    return 0;
}

会 T的纯队列做法:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
#define  PII pair<int,int>
deque<PII > q;
vector<int> ans;
PII pos[maxn];
 
int gcd(int a,int b){
    return b == 0 ? a:gcd(b,a % b);
}
 
 
int main()
{
    int t,n,a,cnt;
    PII x1,x2;
    cin>>t;
    while(t--){
        cnt  = 0;
        q.clear();
        ans.clear();
        cin>>n;
        for(int i = 1;i <= n; i++){
            cin>>a;
            q.push_back({a,i});
        }
        while(!q.empty()){
            x1 = q.front();
            q.pop_front();
            q.push_back(x1);
            x2 = q.front();
            // cout<<x1.first<<" "<<x2.first<<endl; 
            if(gcd(x1.first,x2.first) != 1)
                cnt++;
            else{
                cnt = 0;
                ans.push_back(x2.second);
                q.pop_front();
            }
            if(cnt > q.size() || q.size() == 0)
                break;
        }
        cout<<ans.size()<<" ";
        for(auto i : ans)
            cout<<i <<" ";
        cout<<endl;
    }
 
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值