[CF1483B] Playlist - set
Description
有一个包含 (n) 首歌的歌单,第 (i) 首歌的风格为 (a_i),现在循环播放该歌单(听完最后一首歌后回到第一首歌)。
设当前听完的歌 (B) 风格为 (y) ,上一首听完的歌 (A) 风格为 (x) 。
若 (gcd{(x,y)=1}) ,则删掉歌 (B) ,从原歌单中 (B) 的下一首歌 (C) 开始听(此时不再考虑 (A) 和 (C) 风格的 (gcd) 的关系)。
请求出被删掉的歌以及删歌的顺序。 |
Solution
一个元素,如果它的下一个元素和它的 GCD = 1,那么我们把这个元素叫做关键元素
随着删除的过程,关键元素可能会变成非关键元素,但是非关键元素一定不会变成关键元素
我们维护一个关键元素的集合,每次通过 upper_bound 找到下一个关键元素即可
每次删除元素后,可能要将相关的元素从关键元素集合中删除
代码中有些奇怪的东西(链表指针),开始做暴力用的
#include <bits/stdc++.h>
using namespace std;
#define int long long
int xbound(const set<int> &s, int x)
{
auto tmp = s.upper_bound(x);
if (tmp == s.end())
return *s.begin();
return *tmp;
}
void solve()
{
struct Node
{
int val;
int id;
Node *next;
};
int n;
cin >> n;
vector<Node> nodes(n + 2);
for (int i = 1; i <= n; i++)
cin >> nodes[i].val, nodes[i].id = i;
for (int i = 1; i < n; i++)
nodes[i].next = &nodes[i + 1];
nodes[n].next = &nodes[1];
int cnt = 0;
vector<int> ans;
int siz = n;
set<int> s;
for (int i = 1; i < n; i++)
if (__gcd(nodes[i].val, nodes[i + 1].val) == 1)
s.insert(i);
if (__gcd(nodes[n].val, nodes[1].val) == 1)
s.insert(n);
if (s.size())
{
Node *p = &nodes[xbound(s, 0)];
Node *q = p->next;
int cnt = 0;
while (siz >= 1 && cnt <= n)
{
if (__gcd(p->val, q->val) == 1)
{
p->next = q->next;
ans.push_back(q->id);
siz--;
if (s.find(q->id) != s.end())
s.erase(q->id);
if (s.size() == 0)
break;
p = &nodes[xbound(s, p->id)];
q = p->next;
cnt = 0;
}
else
{
s.erase(p->id);
p = p->next;
q = q->next;
cnt++;
}
}
}
cout << ans.size() << " ";
for (auto i : ans)
cout << i << " ";
cout << endl;
}
signed main()
{
ios::sync_with_stdio(false);
int t;
cin >> t;
while (t--)
{
solve();
}
}