首页 > 代码库 > A.圆环出列

A.圆环出列

A - 圆环出列

Time Limit: 2000/1000 MS (Java/Others)      Memory Limit: 128000/64000 KB (Java/Others)
Submit Status

Problem Description

n个人坐成一个圆环(编号为1 - n),有一个广播在随机报号,每次被点到编号的人出列,若被点到的编号的人已经不在圆环中了,则它左边第一个还在圆环上的人出列,其中编号i左边的人的编号是i-1(i>1),编号1左边的人是n

Input


?每个样例第一行输入两个数n(1≤n≤10^6),q(1≤q≤10^5 && q≤n)
?接下来q行每行有一个数id(1≤id≤n),表示被点到的编号
所有样例的q的和不超过10^7

Output

对于每组数据输出一行,形如"Case #X:",X表示第几个样例

对于每个被点到的编号,输出一行出列的人的编号

Sample Input

10 3
6
6
6

Sample Output

Case #1:
6
5
4

技术分享
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long LL;
 4 const int N=1e6+10;
 5 const int INF=0x3f3f3f3f;
 6 int cas=1,T;
 7 int pa[N],n,q;
 8 int tot=0;
 9 int find(int x) 
10 { 
11     tot++;
12     return x==pa[x]?x:pa[x]=find(pa[x]); 
13 }
14 int main()
15 {
16 //    freopen("1.in","w",stdout);
17     freopen("1.in","r",stdin);
18     freopen("1.out","w",stdout);
19 //    scanf("%d",&T);
20     int sumn=0,sumq=0;
21     while(scanf("%d%d",&n,&q)==2)
22     {
23         sumn+=n;sumq+=q;
24         for(int i=1;i<=n;i++) pa[i]=i;
25         pa[0]=n;
26         printf("Case #%d:\n",cas++);
27         while(q--)
28         {
29             int x;
30             scanf("%d",&x);
31             x=find(x);
32             printf("%d\n",x);
33             pa[x]=x-1;
34         }
35     }
36     cerr<<"time="<<(double)clock()/CLOCKS_PER_SEC<<" "<<sumn<<" "<<sumq<<" "<<tot<<endl;
37     return 0;
38 }
solve.cpp

题解:

这道题的代码本来是用来生成数据的,要生成[1,n]区间内的所有数,有一个随机数生成器在生成数字,但每个数只能出现一遍,于是当这个数不存在时就取这个数的下一个数
做法是用并查集,每个根表示存在的数,当一个数出现过之后就将这个数连到后一个根上去,记得路径压缩

 

由于当时出题时题目顺序没部署好,这题放在了第一题,而且题面是中文的,题意易懂,师弟上来就开始做这题,半个小时左右有个师弟A了,然后就把榜带歪了,很多人在卡这道题不去看后面的水题,其实这道题并不好想,而且专门卡了log的做法,最终也只是5个人AC

A.圆环出列