[关闭]
@dxbdly 2020-12-20T07:01:31.000000Z 字数 2676 阅读 195

C2020 2020.10.24模拟赛

信息学——模拟赛

考试情况

预计分数VS实际分数

预计分数:

T1 T2 T3 总分
100 100 100 300

实际分数:

T1 T2 T3 总分
100 100 60 260

T1 cows

分析

显然的二分答案,二分R, K,从第一堆草枚举,对于每一堆还没覆盖的草,以当前草为左端点,算出右端点,以此覆盖与K比较即可。

  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,k;
  16. int a[50005],maxx;
  17. inline bool check(int r)
  18. {
  19. int tot=1,now=a[1]+r*2;
  20. for (register int i=2;i<=n;++i)
  21. if (a[i]>now)
  22. now=a[i]+r*2,tot++;
  23. return tot<=k;
  24. }
  25. inline void erfen()
  26. {
  27. int l=-1,r=maxx+1;
  28. while (l+1<r)
  29. {
  30. int mid=(l+r)>>1;
  31. if (check(mid))
  32. r=mid;
  33. else
  34. l=mid;
  35. }
  36. printf("%d",r);
  37. }
  38. int main(){
  39. freopen("cows.in","r",stdin);
  40. freopen("cows.out","w",stdout);
  41. n=read(),k=read();
  42. for (register int i=1;i<=n;++i)
  43. a[i]=read(),maxx=max(maxx,a[i]);
  44. sort(a+1,a+n+1);
  45. erfen();
  46. return 0;
  47. }

T2 div7

分析

一段区间的和被7整除,看到区间和自然想到前缀和。

进一步想到如果两个前缀和 7同余,那么他们俩相减得到的区间就是被7整除的。

那么只要依次求前缀和,找到与当前余数相同的最早的那个点相减即可。

  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;
  16. int a[50005],f[7],sum,ans;
  17. signed main(){
  18. freopen("div7.in","r",stdin);
  19. freopen("div7.out","w",stdout);
  20. n=read();
  21. for (register int i=1;i<=n;++i)
  22. {
  23. a[i]=read(),a[i]%=7,sum=(sum+a[i])%7;
  24. if (!a[i])
  25. ans=max(ans,1);
  26. if (!f[sum])
  27. f[sum]=i;
  28. ans=max(ans,i-f[sum]);
  29. }
  30. printf("%d",ans);
  31. return 0;
  32. }

总结与反思

提一句,虽然这题比较水,但其思想其实是来源于“剩余系”,一个很好用的思想。

T3 gates

分析

话说考场莫名掉题面?感觉这翻译有点捞。

显然是要我们求封闭区间的个数。

考虑如何求,发现只要求交点个数即可,但是由于题面说可以重复走,会影响到判断,所以还需开个标记,记录每次走的出发点与方向,计数时终点反方向走到起点的标记必须为0。(说得好像有点抽象,看代码理解吧)

  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. struct node{
  16. int x,y,to;
  17. };
  18. int n,x,y,ans,op;
  19. int go[4][2]={{-1,0},{1,0},{0,-1},{0,1}},vst[2005][2005];
  20. map <node,int> mapp;
  21. char c;
  22. inline bool operator <(node a,node b)
  23. {
  24. return a.x!=b.x?a.x<b.x:(a.y!=b.y?a.y<b.y:a.to<b.to);
  25. }
  26. inline int calc(char c)
  27. {
  28. if (c=='N')
  29. return 0;
  30. if (c=='S')
  31. return 1;
  32. if (c=='W')
  33. return 2;
  34. if (c=='E')
  35. return 3;
  36. }
  37. inline int inv(int x)
  38. {
  39. return x&1?x-1:x+1;
  40. }
  41. int main(){
  42. n=read();
  43. x=1000,y=1000,vst[x][y]=1;
  44. for (register int i=1;i<=n;++i)
  45. {
  46. while (!isalpha(c=getchar()));
  47. int to=calc(c),nx=x+go[to][0],ny=y+go[to][1];
  48. mapp[(node){x,y,to}]=1;
  49. if (vst[nx][ny]&&!mapp[(node){nx,ny,inv(to)}])
  50. ans++;
  51. mapp[(node){nx,ny,inv(to)}]=1,vst[nx][ny]=1;
  52. x=nx,y=ny;
  53. }
  54. printf("%d",ans);
  55. return 0;
  56. };

总结与反思

考场上很多人挂了空间,实际上只需要用map维护,由于题目可以有负数所以需要将范围开大,但显然并没有全部打上标记,会浪费很多空间。

我考场上正向走和反向走都判了然后挂了,解释一下为什么不能判正向,有可能有两个封闭区间有重边,而且是同一个方向走来的,这时候你会少算一个。

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