标签:磁极 P7045 洛谷 int 队列 ans 书虫 金牌
题目
题目链接:https://www.luogu.com.cn/problem/P7045
书虫正在整理他的 \(n\) 块金牌,他发现所有金牌都是有磁性的!形式地说,每块金牌属于一种磁极,磁极有很多种。两块相邻的金牌磁极相同则相互排斥,不同则相互吸引。
书虫不知道每块金牌的磁极,他只能通过把两块金牌靠近的方式得知它们是相同磁极还是不同磁极。换句话说,你可以进行不超过 \(Q\) 次交互,每次向交互库询问两个数 \(x,y\),交互库会返回第 \(x\) 块金牌和第 \(y\) 块金牌是排斥还是吸引。金牌从 \(0\) 到 \(n-1\) 编号。
书虫希望把他的金牌排成一个排列,满足任意两块相邻的金牌都相吸引,请你帮他排出 任意一个 合法的排列,或者告诉他无解。
思路
QuantAsk YYDS!
有一个很直接的想法是我们枚举每一块金牌 \(i\),将前 \(i\) 块中剩余的金牌扔到队列里。如果第 \(i\) 块金牌和再队列里的金牌不一致,那么就将这两块金牌都加入答案序列,否则将 \(i\) 压入队列中。
那么最后有若干个多出来的互相排斥的金牌在队列中,我们就枚举答案序列,如果相邻两项均与在队列中的金牌吸引,那么就在它们之间插入一块金牌。
由于我们最开始将 \(0\) 直接加入到答案序列中,所以最多会有 \(2(n-1)=2n-2\) 次交互。
代码
#include <bits/stdc++.h>
using namespace std;
const int N=100010;
int Q,n,m,ret,ans[N];
queue<int> q;
void prework()
{
while (q.size()) q.pop();
m=1; ans[1]=0;
}
int main()
{
scanf("%d",&Q);
while (Q--)
{
scanf("%d%d",&n,&m);
prework();
for (int i=1;i<n;i++)
if (!q.size())
{
printf("%d %d\n",i,ans[m]);
fflush(stdout);
scanf("%d",&ret);
if (ret) ans[++m]=i;
else q.push(i);
}
else
{
printf("%d %d\n",i,q.front());
fflush(stdout);
scanf("%d",&ret);
if (ret) ans[++m]=i,ans[++m]=q.front(),q.pop();
else q.push(i);
}
for (int i=2*m;i>=1;i-=2)
ans[i]=ans[i/2],ans[i-1]=-1;
if (q.size())
{
bool last=1;
for (int i=2;i<=2*m;i+=2)
{
printf("%d %d\n",q.front(),ans[i]);
fflush(stdout);
scanf("%d",&ret);
if (ret && last) ans[i-1]=q.front(),q.pop();
if (!q.size()) break;
last=ret;
}
}
if (q.size()) printf("-1\n");
else
{
printf("%d\n",n);
for (int i=1;i<=2*m;i++)
if (ans[i]!=-1) printf("%d ",ans[i]);
printf("\n");
}
fflush(stdout);
}
return 0;
}
标签:磁极,P7045,洛谷,int,队列,ans,书虫,金牌 来源: https://www.cnblogs.com/stoorz/p/13909506.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。