kick start 2019 round D T2题解
题目大意:由N个房子围成一个环,G个人分别顺时针/逆时针在房子上走,一共走M分钟,每分钟结束,每个人顺/逆时针走到相邻的房子。对于每个房子都会记录最后时刻到达的人(可能是一群人)。最终输出每个人会被几个房子记录。
数据范围:N<=1e5,G<=1e5,M<=1e9,多组测试数据。
解题思路:比赛时没做出来第二个测试点,有点失了智。。。看了下题解马上就有了想法。关键点在于①将顺时针逆时针分开考虑②从走过M步的最终状态向前思考③从单个人变成一群人代码的准确性④代码的准确性。
我的想法是:先将顺时针单独考虑,然后得到最终状态,对于N个屋子进行逆时针循环(由于从最终状态倒退),若该房子有一群人,则记录此编号,并刷新时间戳(M),若该房子没有人,则根据时间戳标记之前记录的编号。对逆时针进行同样的操作。最终统一看,对于每一个房子:顺逆时针时间戳不同则将较大的人群num++,相同则都num++。最终输出即可。
由于我的stl还不熟练,完全的C风格让代码较为复杂,但真的是一个好题,做得很慢,估计写了45min吧。
最终代码:
1 #include <stdio.h> 2 3 using namespace std; 4 5 int st[100010]; 6 int clock[100010]; 7 int lis[100010]; 8 int gcst[100010],gast[100010],gcfi[100010],gafi[100010]; 9 int gcnum[100010],ganum[100010]; 10 int tima[100010],timc[100010],lasa[100010],lasc[100010]; 11 int flag[100010]; 12 13 int mainn() 14 { 15 int n,g,m;scanf("%d%d%d",&n,&g,&m); 16 for (int i=0;i<g;i++) 17 { 18 scanf("%d",&st[i]); 19 char ch=getchar();while (ch==' ') ch=getchar(); 20 if (ch=='A') clock[i]=-1;else clock[i]=1; 21 } 22 int ngc=0,nga=0; 23 for (int i=0;i<=n;i++) flag[i]=-1; 24 for (int i=0;i<g;i++) 25 if (clock[i]>0){ 26 if (flag[st[i]]==-1){ 27 flag[st[i]]=ngc;gcst[ngc]=st[i];lis[i]=ngc++; 28 } 29 else 30 lis[i]=flag[st[i]]; 31 } 32 33 for (int i=0;i<=n;i++) flag[i]=-1; 34 for (int i=0;i<g;i++) 35 if (clock[i]<0){ 36 if (flag[st[i]]==-1){ 37 flag[st[i]]=nga;gast[nga]=st[i];lis[i]=nga++; 38 } 39 else 40 lis[i]=flag[st[i]]; 41 } 42 43 for (int i=0;i<ngc;i++) gcfi[i]= (gcst[i]-1+m)%n+1; 44 for (int i=0;i<nga;i++) gafi[i]= ((gast[i]-1-m)%n+n)%n+1; 45 46 for (int i=0;i<ngc;i++) gcnum[i]=0; 47 for (int i=0;i<nga;i++) ganum[i]=0; 48 49 for (int i=0;i<=n;i++) lasa[i]=lasc[i]=tima[i]=timc[i]=-1; 50 51 int tmp=0,fin=0; 52 for (int i=0;i<ngc;i++){ 53 if (tmp==0) tmp=fin=gcfi[i]; 54 lasc[ gcfi[i] ]=i;timc[ gcfi[i] ]=m; 55 } 56 57 int last=lasc[tmp];int _time=m;tmp=tmp-1;if (tmp==0) tmp=n; 58 while(fin>0 && tmp!=fin){ 59 _time--; 60 if ( lasc[tmp]==-1 && _time>=0 ) 61 lasc[tmp]=last,timc[tmp]=_time; 62 else if ( lasc[tmp]!=-1 ) 63 last=lasc[tmp],_time=m; 64 tmp--;if (tmp==0) tmp=n; 65 } 66 67 tmp=fin=0; 68 for (int i=0;i<nga;i++){ 69 if (tmp==0) tmp=fin=gafi[i]; 70 lasa[gafi[i]]=i;tima[ gafi[i] ]=m; 71 } 72 last=lasa[tmp];_time=m;tmp=tmp%n+1; 73 while (fin>0 && tmp!=fin){ 74 _time--; 75 if ( lasa[tmp]==-1 && _time>=0 ) 76 lasa[tmp]=last,tima[tmp]=_time; 77 else if ( lasa[tmp]!=-1 ) 78 last=lasa[tmp],_time=m; 79 tmp=tmp%n+1; 80 } 81 82 for (int i=0;i<ngc;i++) gcnum[i]=0; 83 for (int i=0;i<nga;i++) ganum[i]=0; 84 85 for (int i=1;i<=n;i++) 86 { 87 if (lasa[i]>=0 && lasc[i]>=0){ 88 if ( tima[i]>timc[i] ) 89 ganum[ lasa[i] ]++; 90 else if (tima[i]<timc[i]) 91 gcnum[ lasc[i] ]++; 92 else 93 ganum[ lasa[i] ]++,gcnum[ lasc[i] ]++; 94 } 95 else if (lasa[i]>=0){ 96 ganum[ lasa[i] ]++; 97 } 98 else if (lasc[i]>=0){ 99 gcnum[ lasc[i] ]++; 100 } 101 } 102 /* 103 printf("\n\n"); 104 for (int i=1;i<=n;i++) 105 printf("%d ",lasc[i]); 106 printf("\n"); 107 for (int i=1;i<=n;i++) 108 printf("%d ",timc[i]); 109 printf("\n"); 110 for (int i=1;i<=n;i++) 111 printf("%d ",lasa[i]); 112 printf("\n"); 113 for (int i=1;i<=n;i++) 114 printf("%d ",tima[i]);*/ 115 for (int i=0;i<g;i++) 116 { 117 if(clock[i]>0) 118 printf(" %d",gcnum[lis[i]]); 119 else 120 printf(" %d",ganum[lis[i]]); 121 } 122 printf("\n"); 123 124 } 125 126 127 128 int main() 129 { 130 int T;scanf("%d",&T); 131 for (int i=1;i<=T;i++) 132 { 133 printf("Case #%d:",i); 134 mainn(); 135 } 136 }
好题,值得重新练习的“模拟题”。
题目链接:https://codingcompetitions.withgoogle.com/kickstart/round/0000000000051061/0000000000161427
浙公网安备 33010602011771号