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

转载于:https://www.cnblogs.com/cdyboke/p/6939048.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值