[关闭]
@dxbdly 2020-12-20T06:59:32.000000Z 字数 4273 阅读 202

C2020 2020.10.31模拟赛

信息学——模拟赛


考试情况

期望得分VS实际得分

期望得分:

T1 T2 T3 总分
100 100 100 300

实际得分:

T1 T2 T3 总分
100 100 10 210

吐槽一句:这几乎三暴力的码力赛实在是打得累……

T1 pairup

分析

可以得到一个显然的贪心:从小到大排序后,所有的首尾组对一定包含最优解。(正确性太显然,不证了)

但我们发现范围最大可到,暴力做显然会T

考虑题面中的范围较小,所以考虑复杂度与有关,显然我们会发现,在暴力匹配的过程中,会有很多冗余,即我们会把相同的两个数匹配多次,考虑去掉这样的冗余。

我们可以按块匹配,这样复杂度就成了

  1. //The code is from dawn_sdy
  2. #include<bits/stdc++.h>
  3. using namespace std;
  4. inline int read()
  5. {
  6. int x=0;
  7. char c=getchar();
  8. bool f=0;
  9. while (!isdigit(c))
  10. f|=(c=='-'),c=getchar();
  11. while (isdigit(c))
  12. x=(x<<3)+(x<<1)+(c^48),c=getchar();
  13. return f?-x:x;
  14. }
  15. int n,ans;
  16. struct node{
  17. int num,val;
  18. }a[100005];
  19. inline bool operator <(node x,node y)
  20. {
  21. return x.val<y.val;
  22. }
  23. int main(){
  24. //freopen("pairup.in","r",stdin);
  25. //freopen("pairup.out","w",stdout);
  26. n=read();
  27. for (register int i=1;i<=n;++i)
  28. a[i].num=read(),a[i].val=read();
  29. sort(a+1,a+n+1);
  30. int r=n,num=a[n].num;
  31. for (register int i=1;i<=r;++i)
  32. {
  33. ans=max(ans,a[i].val+a[r].val);
  34. while (a[i].num>=num)
  35. a[i].num-=num,r--,num=a[r].num;
  36. num-=a[i].num;
  37. }
  38. printf("%d",ans);
  39. return 0;
  40. }

T2 genomics

分析

阅读理解题,题面较难读。

本质就是要我们找符合要求的三元组数量,考虑按题意模拟。

枚举这三个位置,开个标记记录有斑点的串,看无斑点的串是否被打上过标记即可。

  1. //The code is from dawn_sdy
  2. #include<bits/stdc++.h>
  3. using namespace std;
  4. inline int read()
  5. {
  6. int x=0;
  7. char c=getchar();
  8. bool f=0;
  9. while (!isdigit(c))
  10. f|=(c=='-'),c=getchar();
  11. while (isdigit(c))
  12. x=(x<<3)+(x<<1)+(c^48),c=getchar();
  13. return f?-x:x;
  14. }
  15. int n,m;
  16. int a[505][55],b[505][55],bj[55][55][55],cnt[55][4],flag,ans;
  17. int main(){
  18. //freopen("cownomics.in","r",stdin);
  19. //freopen("cownomics.out","w",stdout);
  20. n=read(),m=read();
  21. char c;
  22. for (register int i=1;i<=n;++i)
  23. {
  24. for (register int j=1;j<=m;++j)
  25. {
  26. while (!isalpha(c=getchar()));
  27. a[i][j]=(c=='A'?1:(c=='C'?2:(c=='G'?3:4)));
  28. }
  29. }
  30. for (register int i=1;i<=n;++i)
  31. {
  32. for (register int j=1;j<=m;++j)
  33. {
  34. while (!isalpha(c=getchar()));
  35. b[i][j]=(c=='A'?1:(c=='C'?2:(c=='G'?3:4)));
  36. }
  37. }
  38. for (register int i=1;i<=m;++i)
  39. for (register int j=i+1;j<=m;++j)
  40. for (register int k=j+1;k<=m;++k)
  41. {
  42. flag=1;
  43. for (register int p=1;p<=n;++p)
  44. bj[a[p][i]][a[p][j]][a[p][k]]=1;
  45. for (register int p=1;p<=n;++p)
  46. if (bj[b[p][i]][b[p][j]][b[p][k]])
  47. flag=0;
  48. ans+=flag;
  49. for (register int p=1;p<=n;++p)
  50. bj[a[p][i]][a[p][j]][a[p][k]]=0;
  51. }
  52. printf("%d",ans);
  53. return 0;
  54. }

反思与总结

复杂度跑满了似乎可以被卡掉的,但偏偏跑不满。

当然这里实现的时候,一个非常常用的卡常技巧就是很多时候数组清空是可以不用的,只把用过的清零,这样复杂度不容易跑满。

T3 where

分析

可以看到非常小,而也没有其他的值非常大的,基本就考虑模拟了。

首先用的时间枚举矩形的两个端点(左上与右下)。

然后枚举这个矩形中的每个点,统计颜色,通过BFS求联通块,这里复杂度

总复杂度(这复杂度……)

但到这里还不行,题目还要求考虑包含的情况,所以我们需要把每个解的矩形(左上端点与右下端点)存下来判断一遍包含关系。

  1. //The code is from dawn_sdy
  2. #include<bits/stdc++.h>
  3. #define mp make_pair
  4. using namespace std;
  5. inline int read()
  6. {
  7. int x=0;
  8. char c=getchar();
  9. bool f=0;
  10. while (!isdigit(c))
  11. f|=(c=='-'),c=getchar();
  12. while (isdigit(c))
  13. x=(x<<3)+(x<<1)+(c^48),c=getchar();
  14. return f?-x:x;
  15. }
  16. struct node{
  17. int sx,sy,ex,ey;
  18. };
  19. int n;
  20. int a[25][25],go[4][2]={{0,1},{0,-1},{1,0},{-1,0}},col,col1,col2,tot1,tot2,ans;
  21. bool b[35],vst[25][25];
  22. vector <node> vec;
  23. queue < pair<int,int> > q;
  24. inline void search(int lx,int ly,int rx,int ry,int sx,int sy,int col)
  25. {
  26. q.push(mp(sx,sy)),vst[sx][sy]=1;
  27. while (!q.empty())
  28. {
  29. int x=q.front().first,y=q.front().second;
  30. q.pop();
  31. for (register int i=0;i<4;++i)
  32. {
  33. int nx=x+go[i][0],ny=y+go[i][1];
  34. if (nx<lx||ny<ly||nx>rx||ny>ry||vst[nx][ny]||a[nx][ny]!=col)
  35. continue;
  36. q.push(mp(nx,ny)),vst[nx][ny]=1;
  37. }
  38. }
  39. }
  40. inline bool check(int x)
  41. {
  42. int sz=vec.size();
  43. for (register int i=0;i<sz;++i)
  44. if (i!=x&&vec[i].sx<=vec[x].sx&&vec[i].sy<=vec[x].sy&&vec[i].ex>=vec[x].ex&&vec[i].ey>=vec[x].ey)
  45. return 0;
  46. return 1;
  47. }
  48. inline bool work(int sx,int sy,int ex,int ey)
  49. {
  50. memset(vst,0,sizeof(vst));
  51. memset(b,0,sizeof(b));
  52. col=col1=col2=tot1=tot2=0;
  53. for (register int x=sx;x<=ex;++x)
  54. for (register int y=sy;y<=ey;++y)
  55. if (!vst[x][y])
  56. {
  57. if (!b[a[x][y]])
  58. {
  59. col++;
  60. if (!col1)
  61. col1=a[x][y],b[a[x][y]]=1;
  62. else
  63. if (!col2)
  64. col2=a[x][y],b[a[x][y]]=1;
  65. if (col>2)
  66. return 0;
  67. }
  68. if (a[x][y]==col1)
  69. search(sx,sy,ex,ey,x,y,a[x][y]),tot1++;
  70. if (a[x][y]==col2)
  71. search(sx,sy,ex,ey,x,y,a[x][y]),tot2++;
  72. }
  73. if ((tot1==1&&tot2>=2)||(tot2==1&&tot1>=2))
  74. return 1;
  75. return 0;
  76. }
  77. int main(){
  78. //freopen("where.in","r",stdin);
  79. //freopen("where.out","w",stdout);
  80. n=read();
  81. char c;
  82. for (register int i=1;i<=n;++i)
  83. for (register int j=1;j<=n;++j)
  84. {
  85. while (!isalpha(c=getchar()));
  86. a[i][j]=c-'A'+1;
  87. }
  88. for (register int sx=1;sx<=n;++sx)
  89. for (register int sy=1;sy<=n;++sy)
  90. for (register int ex=sx;ex<=n;++ex)
  91. for (register int ey=sy;ey<=n;++ey)
  92. if (work(sx,sy,ex,ey))
  93. vec.push_back((node){sx,sy,ex,ey});
  94. int sz=vec.size();
  95. for (register int i=0;i<sz;++i)
  96. if (check(i))
  97. ans++;
  98. printf("%d",ans);
  99. return 0;
  100. }

反思与总结

细节较多,这种算法比较明显的题就拼码力,细节和实现技巧了。

事实证明实现技巧比较重要。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注