[关闭]
@Mankeus 2018-07-22T11:25:32.000000Z 字数 4544 阅读 565

T1 括号

30-40做法:

将括号序列的每个子序列选出,判断是否合理,暴力搜索匹配括号。时间复杂度

60分做法:

这就需要研究一下,题目中所给的大数据了,因为有特殊条件限制,大数据比起前面的数据更好拿分,想一想左括号全部在右括号左侧的话,我们可以考虑贪心,讲左括号部分与右括号部分价值处理出来,然后排一下序,当然谁大选谁了。

100分:

其实题目中的大部分数据已经解决了,现在我们需要考虑对于的范围考虑,考虑DP了。
为考虑了前i个括号,目前有j个左括号待匹配的最大权值和,那么转移的话分以下两种情况:



注意一下边界就好了,最后答案是
时间复杂度:

代码

  1. #include <cstdio>
  2. #include <vector>
  3. #include <algorithm>
  4. using namespace std;
  5. #define N 200000 + 5
  6. #define INF 0x3f3f3f3f
  7. int n, ans, A[N];
  8. char s[N];
  9. namespace DP
  10. {
  11. int Dp[2][N];
  12. void Init()
  13. {
  14. Dp[0][0] = 0;
  15. for (int i = 1; i <= n; i ++)
  16. Dp[0][i] = -INF;
  17. }
  18. int Solve()
  19. {
  20. Init();
  21. for (int l = 1; l <= n; l ++)
  22. {
  23. for (int i = 0; i <= n; i ++)
  24. {
  25. Dp[1][i] = Dp[0][i];
  26. if (s[l] == '(' && i)
  27. Dp[1][i] = max(Dp[1][i], Dp[0][i - 1] + A[l]);
  28. else if (s[l] == ')' && i < n)
  29. Dp[1][i] = max(Dp[1][i], Dp[0][i + 1] + A[l]);
  30. }
  31. for (int i = 0; i <= n; i ++)
  32. Dp[0][i] = Dp[1][i];
  33. }
  34. return Dp[0][0];
  35. }
  36. }
  37. namespace Greedy
  38. {
  39. vector<int> L, R;
  40. bool cmp(int u, int v)
  41. {
  42. return u > v;
  43. }
  44. void Init()
  45. {
  46. L.clear();
  47. R.clear();
  48. }
  49. int Solve()
  50. {
  51. Init();
  52. for (int i = 1; i <= n; i ++)
  53. {
  54. if (s[i] == '(')
  55. L.push_back(A[i]);
  56. else R.push_back(A[i]);
  57. }
  58. sort(L.begin(), L.end(), cmp);
  59. sort(R.begin(), R.end(), cmp);
  60. int ret = 0;
  61. for (int i = 0; i < L.size() && i < R.size(); i ++)
  62. {
  63. int tuple = L[i] + R[i];
  64. if (tuple < 0) break ;
  65. ret += tuple;
  66. }
  67. return ret;
  68. }
  69. }
  70. int main()
  71. {
  72. freopen("bracket.in", "r", stdin);
  73. freopen("bracket.out", "w", stdout);
  74. scanf("%d", &n);
  75. scanf("%s", s + 1);
  76. for (int i = 1; i <= n; i ++)
  77. scanf("%d", A + i);
  78. if (n <= 2000)
  79. ans = DP::Solve();
  80. else ans = Greedy::Solve();
  81. printf("%d\n", ans);
  82. return 0;
  83. }

T2 连连看

emm...直接输出k可以得15分。

40-60分

枚举每一张牌,进行搜索,以转弯次数作为判断标准,看是否可以搜到。
时间复杂度:

100分

此处输入图片的描述

设1和2两个点为一对点,那么从1->2(2->1)无非只有以下4种情况,所以我们可以枚举每一个第一次转弯的点,判断是否可行。

代码

  1. #include <cstdio>
  2. #include <algorithm>
  3. using namespace std;
  4. #define N 1000 + 5
  5. #define K 5000 + 5
  6. int n, m, k, ans;
  7. int Row[N][N], Column[N][N];
  8. struct Point2D
  9. {
  10. int x, y;
  11. Point2D() : Point2D(0, 0) {}
  12. Point2D(int x, int y) : x(x), y(y) {}
  13. }Pos[K][2];
  14. int main()
  15. {
  16. freopen("linking.in", "r", stdin);
  17. freopen("linking.out", "w", stdout);
  18. scanf("%d%d%d", &n, &m, &k);
  19. for (int i = 1; i <= k; i ++)
  20. for (int j = 0, x, y; j < 2; j ++)
  21. {
  22. scanf("%d%d", &x, &y);
  23. Pos[i][j] = Point2D(x, y);
  24. Row[x][y] = 1, Column[x][y] = 1;
  25. }
  26. for (int i = 1; i <= n; i ++)
  27. for (int j = 1; j <= m; j ++)
  28. {
  29. Row[i][j] += Row[i][j - 1];
  30. Column[i][j] += Column[i - 1][j];
  31. }
  32. for (int i = 1; i <= k; i ++)
  33. {
  34. bool ok = 0;
  35. for (int r = 1; !ok && r <= n; r ++)
  36. {
  37. int x_1 = Pos[i][0].x, x_2 = r, y = Pos[i][0].y;
  38. if (x_1 > x_2) swap(x_1, x_2);
  39. if (Column[x_2][y] - Column[x_1 - 1][y] > 1) continue ;
  40. int y_1 = Pos[i][0].y, y_2 = Pos[i][1].y;
  41. if (y_1 > y_2) swap(y_1, y_2);
  42. if (Row[r][y_2 - 1] - Row[r][y_1] > 0) continue ;
  43. x_1 = Pos[i][1].x, x_2 = r, y = Pos[i][1].y;
  44. if (x_1 > x_2) swap(x_1, x_2);
  45. if (Column[x_2][y] - Column[x_1 - 1][y] > 1) continue ;
  46. ok = true;
  47. }
  48. for (int c = 1; !ok && c <= m; c ++)
  49. {
  50. int y_1 = Pos[i][0].y, y_2 = c, x = Pos[i][0].x;
  51. if (y_1 > y_2) swap(y_1, y_2);
  52. if (Row[x][y_2] - Row[x][y_1 - 1] > 1) continue ;
  53. int x_1 = Pos[i][0].x, x_2 = Pos[i][1].x;
  54. if (x_1 > x_2) swap(x_1, x_2);
  55. if (Column[x_2 - 1][c] - Column[x_1][c] > 0) continue ;
  56. y_1 = Pos[i][1].y, y_2 = c, x = Pos[i][1].x;
  57. if (y_1 > y_2) swap(y_1, y_2);
  58. if (Row[x][y_2] - Row[x][y_1 - 1] > 1) continue ;
  59. ok = true;
  60. }
  61. ans += ok;
  62. }
  63. printf("%d\n", ans);
  64. return 0;
  65. }

T3 数

30分

照题面模拟,需要手写两个函数。
判断大小函数:

  1. bool bijiao(int x)
  2. {
  3. int s[1000],ls=0,p;
  4. while(x)
  5. {
  6. s[++ls]=x%10;
  7. x/=10;
  8. }
  9. for(int i=1;i<=ls;i++)
  10. {
  11. if(s[i]!=0)
  12. {
  13. p=i;
  14. break;
  15. }
  16. }
  17. int l=p,r=ls;
  18. while(l<r)
  19. {
  20. if(s[l]>s[r])return 1;
  21. if(s[l]<s[r])return 0;
  22. l++;r--;
  23. } // 1 表示g(x)大, 0表示原数大。
  24. return 1;
  25. }

转为函数

  1. int g(int x)
  2. {
  3. int s[1000],ls=0,p,k=0,sum=0;
  4. while(x)
  5. {
  6. s[++ls]=x%10;
  7. x/=10;
  8. }
  9. for(int i=1;i<=ls;i++)
  10. {
  11. if(s[i]!=0)
  12. {
  13. p=i;
  14. break;
  15. }
  16. else k++;
  17. }
  18. for(int i=p;i<=ls;i++)sum=sum*10+s[i];
  19. for(int i=1;i<=k;i++)sum*=10;
  20. return sum;
  21. }

75分

树上倍增,每一个数字都有一个值预期相对,那么可以在之间建一条边,最终形成一棵树,那么要求值得话,就可以树上倍增求值。

100分

需要离线做,预处理出的数的所对应得值,建出一棵查询树,每次询问就好了。

代码

  1. #include <cstdio>
  2. #include <algorithm>
  3. using namespace std;
  4. #define N 10000000 + 5
  5. #define Q 200000 + 5
  6. int n, htot, qtot, sz, Pow10[N], End10[N], G[N], Head[N], qHead[N], Stack[N], Ans[Q];
  7. struct Edge
  8. {
  9. int next, node;
  10. }h[N];
  11. struct Query
  12. {
  13. int next, k, id;
  14. }q[Q];
  15. void addedge(int u, int v)
  16. {
  17. h[++ htot].next = Head[u], Head[u] = htot;
  18. h[htot].node = v;
  19. }
  20. void addquery(int x, int k, int id)
  21. {
  22. q[++ qtot].next = qHead[x], qHead[x] = qtot;
  23. q[qtot].k = k, q[qtot].id = id;
  24. }
  25. void Prepare()
  26. {
  27. Pow10[0] = 1, End10[0] = 1;
  28. for (int i = 1; i < N; i ++)
  29. {
  30. int i_div_10 = i / 10;
  31. int i_mod_10 = i - i_div_10 * 10;
  32. Pow10[i] = Pow10[i_div_10] * 10;
  33. G[i] = G[i_div_10] + i_mod_10 * Pow10[i_div_10];
  34. if (i_mod_10 == 0)
  35. End10[i] = End10[i_div_10] * 10;
  36. else End10[i] = 1;
  37. }
  38. for (int i = 1; i < N; i ++)
  39. {
  40. G[i] = G[i] * End10[i];
  41. int f_i = (i <= G[i] ? i - 1 : G[i]);
  42. addedge(f_i, i);
  43. }
  44. }
  45. void dfs(int z)
  46. {
  47. Stack[++ sz] = z;
  48. for (int i = qHead[z]; i; i = q[i].next)
  49. {
  50. int k = q[i].k, id = q[i].id;
  51. Ans[id] = (k >= sz ? 0 : Stack[sz - k]);
  52. }
  53. for (int i = Head[z]; i; i = h[i].next)
  54. {
  55. int d = h[i].node;
  56. dfs(d);
  57. }
  58. Stack[sz --] = 0;
  59. }
  60. int main()
  61. {
  62. freopen("num.in", "r", stdin);
  63. freopen("num.out", "w", stdout);
  64. Prepare();
  65. scanf("%d", &n);
  66. for (int i = 1, x, k; i <= n; i ++)
  67. {
  68. scanf("%d%d", &x, &k);
  69. addquery(x, k, i);
  70. }
  71. dfs(0);
  72. for (int i = 1; i <= n; i ++)
  73. printf("%d\n", Ans[i]);
  74. return 0;
  75. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注