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
时间: 2024-10-13 20:41:33