快noip了就乱做一下历年的noip题目咯..


noip2014 飞扬的小鸟

其实这道题并不是很难,但是就有点难搞 听说男神错了一个小时..

就是$f_{i,j}$表示在第$i$个位置高度为$j$的时候最小点击次数

递推的话对于上升的情况只做一次,后面几次在后面再做..

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <cstdlib>
  4. #include <algorithm>
  5. using namespace std;
  6. const int Maxn = 10010;
  7. const int Maxm = 1010;
  8. const int inf = 1e9;
  9. int f[2][Maxm];
  10. int n, m, K;
  11. int l[Maxn], u[Maxn]; bool p[Maxn];
  12. int X[Maxn], Y[Maxn];
  13. int _min ( int x, int y ){ return x < y ? x : y; }
  14. int main (){
  15. int i, j, k;
  16. scanf ( "%d%d%d", &n, &m, &K );
  17. l[0] = 0; u[0] = m+1;
  18. for ( i = 1; i <= n; i ++ ){ scanf ( "%d%d", &X[i], &Y[i] ); l[i] = 0; u[i] = m+1; }
  19. for ( i = 1; i <= K; i ++ ){
  20. int x;
  21. scanf ( "%d", &x );
  22. p[x] = true;
  23. scanf ( "%d%d", &l[x], &u[x] );
  24. }
  25. int st = 0;
  26. for ( i = 0; i <= m; i ++ ) f[st][i] = 0;
  27. int num = 0;
  28. for ( i = 1; i <= n; i ++ ){
  29. st = st^1;
  30. for ( j = 0; j <= m; j ++ ) f[st][j] = inf;
  31. bool bk = false;
  32. for ( j = l[i-1]+1; j < u[i-1]; j ++ ){
  33. if ( f[st^1][j] == inf ) continue;
  34. bk = true;
  35. f[st][_min(j+X[i],m)] = _min ( f[st][_min(j+X[i],m)], f[st^1][j]+1 );
  36. }
  37. for ( j = 0; j <= m; j ++ ){
  38. if ( f[st][j] != inf ) f[st][_min(j+X[i],m)] = _min ( f[st][_min(j+X[i],m)], f[st][j]+1 );
  39. }
  40. for ( j = l[i-1]+1; j < u[i-1]; j ++ ){
  41. if ( f[st^1][j] == inf ) continue;
  42. if ( j-Y[i] > l[i] && j-Y[i] < u[i] ) f[st][j-Y[i]] = _min ( f[st][j-Y[i]], f[st^1][j] );
  43. }
  44. if ( bk == false ){ printf ( "0\n%d\n", num-1 ); return 0; }
  45. if ( p[i] == true ) num ++;
  46. }
  47. int ans = inf;
  48. for ( i = 1; i <= m; i ++ ) ans = _min ( ans, f[st][i] );
  49. printf ( "1\n%d\n", ans );
  50. return 0;
  51. }

  


noip2013 货车运输

就是裸的最大瓶颈树..

通俗点说就是最大生成树再用st表维护一下路径最小值..

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <cstdlib>
  4. #include <algorithm>
  5. using namespace std;
  6. const int Maxn = 10010;
  7. const int Maxm = 50010;
  8. struct node {
  9. int y, next, d;
  10. }a[Maxn*2]; int first[Maxn], len;
  11. void ins ( int x, int y, int d ){
  12. len ++;
  13. a[len].y = y; a[len].d = d;
  14. a[len].next = first[x]; first[x] = len;
  15. }
  16. struct lnode {
  17. int x, y, d;
  18. }list[Maxm];
  19. bool cmp ( lnode x, lnode y ){ return x.d > y.d; }
  20. int n, m, q;
  21. int fa[Maxn]; bool fw[Maxn];
  22. int ff ( int x ){
  23. if ( fa[x] == x ) return x;
  24. return fa[x] = ff (fa[x]);
  25. }
  26. int minn[Maxn][15], fat[Maxn][15], dep[Maxn];
  27. int _min ( int x, int y ){ return x < y ? x : y; }
  28. void dfs ( int x, int f ){
  29. fw[x] = true;
  30. for ( int i = 1; i <= 14; i ++ ){
  31. fat[x][i] = fat[fat[x][i-1]][i-1];
  32. minn[x][i] = _min ( minn[x][i-1], minn[fat[x][i-1]][i-1] );
  33. }
  34. for ( int k = first[x]; k; k = a[k].next ){
  35. int y = a[k].y;
  36. if ( y == f ) continue;
  37. fat[y][0] = x;
  38. minn[y][0] = a[k].d;
  39. dep[y] = dep[x]+1;
  40. dfs ( y, x );
  41. }
  42. }
  43. int lca ( int x, int y ){
  44. int ret = 0x7fffffff;
  45. if ( dep[x] < dep[y] ) swap ( x, y );
  46. for ( int i = 14; i >= 0; i -- ){
  47. if ( dep[fat[x][i]] >= dep[y] ){
  48. ret = _min ( ret, minn[x][i] );
  49. x = fat[x][i];
  50. }
  51. }
  52. if ( x == y ) return ret;
  53. for ( int i = 14; i >= 0; i -- ){
  54. if ( fat[x][i] != fat[y][i] ){
  55. ret = _min ( ret, minn[x][i] );
  56. ret = _min ( ret, minn[y][i] );
  57. x = fat[x][i]; y = fat[y][i];
  58. }
  59. }
  60. return _min ( ret, _min ( minn[x][0], minn[y][0] ) );
  61. }
  62. int main (){
  63. int i, j, k;
  64. scanf ( "%d%d", &n, &m );
  65. for ( i = 1; i <= m; i ++ ){
  66. scanf ( "%d%d%d", &list[i].x, &list[i].y, &list[i].d );
  67. }
  68. sort ( list+1, list+m+1, cmp );
  69. for ( i = 1; i <= n; i ++ ) fa[i] = i;
  70. for ( i = 1; i <= m; i ++ ){
  71. int fx = ff (list[i].x), fy = ff (list[i].y);
  72. if ( fx != fy ){
  73. fa[fy] = fx;
  74. ins ( list[i].x, list[i].y, list[i].d );
  75. ins ( list[i].y, list[i].x, list[i].d );
  76. }
  77. }
  78. for ( i = 1; i <= n; i ++ ){
  79. if ( fw[i] == false ){ dep[i] = 1; dfs ( i, 0 ); }
  80. }
  81. scanf ( "%d", &q );
  82. for ( i = 1; i <= q; i ++ ){
  83. int x, y;
  84. scanf ( "%d%d", &x, &y );
  85. int fx = ff (x), fy = ff (y);
  86. if ( fx != fy ) printf ( "-1\n" );
  87. else printf ( "%d\n", lca ( x, y ) );
  88. }
  89. return 0;
  90. }

  


noip2015 跳石头

二分答案,然后找第一个距离超过这个答案的使用,扫一遍即可

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <cstdlib>
  4. #include <algorithm>
  5. using namespace std;
  6. const int Maxn = 50010;
  7. int a[Maxn], n, m, L;
  8. int main (){
  9. int i, j, k;
  10. scanf ( "%d%d%d", &L, &n, &m );
  11. for ( i = 1; i <= n; i ++ ) scanf ( "%d", &a[i] );
  12. a[++n] = L;
  13. int l = 1, r = L, ret;
  14. while ( l <= r ){
  15. int mid = ( l + r ) >> 1;
  16. int last = 0, sum = 0;
  17. for ( i = 1; i <= n; i ++ ){
  18. if ( a[i]-last >= mid ) last = a[i];
  19. else sum ++;
  20. }
  21. if ( sum <= m ){ ret = mid; l = mid+1; }
  22. else r = mid-1;
  23. }
  24. printf ( "%d\n", ret );
  25. return 0;
  26. }

  


noip2015 子串

哇我去年居然会做这道题 然而我现在好像不会了..

$f_{i,j,k}$表示现在在第$i$块,小串匹配到$j$,大串匹配到$k$的方案数

然后就可以这样搞:$$f_{i,j,k}=\sum\limits_{p=0}^{k-1}f_{i-1,j-1,p}+f_{i,j-1,k-1}\times (s2[j-1]==s1[k-1])$$

那么对于前面的只要维护一个前缀和就可以了..

再给一道题吧,也是前缀和相关:CodeForces 587B 记得当年就是从这题吸取了经验的(感谢胖涛..)

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <cstdlib>
  4. #include <algorithm>
  5. using namespace std;
  6. const int Maxn = 1010;
  7. const int Maxm = 210;
  8. const int Mod = 1000000007;
  9. char a[Maxn], b[Maxm];
  10. int n, m, K;
  11. int f[2][Maxm][Maxn];
  12. int main (){
  13. int i, j, k;
  14. scanf ( "%d%d%d", &n, &m, &K );
  15. scanf ( "%s", a+1 );
  16. scanf ( "%s", b+1 );
  17. int st = 0;
  18. for ( i = 0; i <= n; i ++ ) f[0][0][i] = 1;
  19. for ( k = 1; k <= K; k ++ ){
  20. st = st^1;
  21. memset ( f[st], 0, sizeof (f[st]) );
  22. for ( i = 1; i <= m; i ++ ){
  23. for ( j = 1; j <= n; j ++ ){
  24. if ( b[i] == a[j] ){
  25. f[st][i][j] = ( f[st][i][j] + f[st^1][i-1][j-1] ) % Mod;
  26. if ( b[i-1] == a[j-1] ) f[st][i][j] = ( f[st][i][j] + f[st][i-1][j-1] ) % Mod;
  27. }
  28. }
  29. }
  30. for ( i = 1; i <= m; i ++ ){
  31. for ( j = 1; j <= n; j ++ ) f[st][i][j] = ( f[st][i][j] + f[st][i][j-1] ) % Mod;
  32. }
  33. }
  34. printf ( "%d\n", f[st][m][n] );
  35. return 0;
  36. }

  


noip2015 运输计划

先预处理每条路径长度,找出最长的那条记为$ss$

二分答案,超过该答案的路径在树上差分标记一下,那么如果某个点子树所有标记和等于超过的路径数,证明该点与其父亲的边可能要割

然后在这些边中找到最大值,看$ss$减去这个值是否在二分的答案以内就行了

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <cstdlib>
  4. #include <algorithm>
  5. using namespace std;
  6. const int Maxn = 300010;
  7. struct node {
  8. int y, next, d;
  9. }a[Maxn*2]; int first[Maxn], len;
  10. void ins ( int x, int y, int d ){
  11. len ++;
  12. a[len].y = y; a[len].d = d;
  13. a[len].next = first[x]; first[x] = len;
  14. }
  15. int n, m;
  16. int fa[Maxn][23], sum[Maxn][23], dep[Maxn];
  17. void dfs ( int x, int f ){
  18. for ( int i = 1; i <= 22; i ++ ){
  19. fa[x][i] = fa[fa[x][i-1]][i-1];
  20. sum[x][i] = sum[x][i-1] + sum[fa[x][i-1]][i-1];
  21. }
  22. for ( int k = first[x]; k; k = a[k].next ){
  23. int y = a[k].y;
  24. if ( y == f ) continue;
  25. fa[y][0] = x;
  26. sum[y][0] = a[k].d;
  27. dep[y] = dep[x]+1;
  28. dfs ( y, x );
  29. }
  30. }
  31. struct qnode {
  32. int x, y, lca, dist;
  33. }q[Maxn];
  34. void get_lca ( qnode &p ){
  35. int x = p.x, y = p.y;
  36. p.dist = 0;
  37. if ( dep[x] < dep[y] ) swap ( x, y );
  38. for ( int i = 22; i >= 0; i -- ){
  39. if ( dep[fa[x][i]] >= dep[y] ){
  40. p.dist += sum[x][i];
  41. x = fa[x][i];
  42. }
  43. }
  44. if ( x == y ){ p.lca = x; return; }
  45. for ( int i = 22; i >= 0; i -- ){
  46. if ( fa[x][i] != fa[y][i] ){
  47. p.dist += sum[x][i];
  48. p.dist += sum[y][i];
  49. x = fa[x][i];
  50. y = fa[y][i];
  51. }
  52. }
  53. p.dist += sum[x][0]+sum[y][0];
  54. p.lca = fa[x][0];
  55. }
  56. int bj[Maxn];
  57. int _max ( int x, int y ){ return x > y ? x : y; }
  58. int DFS ( int x, int f, int mid ){
  59. int ret = -1;
  60. for ( int k = first[x]; k; k = a[k].next ){
  61. int y = a[k].y;
  62. if ( y == f ) continue;
  63. ret = _max ( DFS ( y, x, mid ), ret );
  64. if ( bj[y] == mid ) ret = _max ( ret, a[k].d );
  65. bj[x] += bj[y];
  66. }
  67. return ret;
  68. }
  69. int main (){
  70. int i, j, k;
  71. scanf ( "%d%d", &n, &m );
  72. for ( i = 1; i < n; i ++ ){
  73. int x, y, d;
  74. scanf ( "%d%d%d", &x, &y, &d );
  75. ins ( x, y, d ); ins ( y, x, d );
  76. }
  77. dfs ( 1, 0 );
  78. int ss = 0;
  79. for ( i = 1; i <= m; i ++ ){
  80. scanf ( "%d%d", &q[i].x, &q[i].y );
  81. get_lca (q[i]);
  82. ss = _max ( ss, q[i].dist );
  83. }
  84. int l = 1, r = ss, ret;
  85. while ( l <= r ){
  86. int mid = ( l + r ) >> 1;
  87. int ssum = 0;
  88. for ( i = 1; i <= n; i ++ ) bj[i] = 0;
  89. for ( i = 1; i <= m; i ++ ){
  90. if ( q[i].dist > mid ){
  91. bj[q[i].x] ++; bj[q[i].y] ++;
  92. bj[q[i].lca] -= 2;
  93. ssum ++;
  94. }
  95. }
  96. if ( ss-DFS ( 1, 0, ssum ) <= mid ){ ret = mid; r = mid-1; }
  97. else l = mid+1;
  98. }
  99. printf ( "%d\n", ret );
  100. return 0;
  101. }

  


noip2013 华容道

记录f[i][j][k][l]为被标记的点在(i,j),空白点在k方向,使其移动到l方向的最小步数

这个东西是可以在$O(n^4)$预处理出来的

那么对于每一个询问,先算出空白点移动到标记点4个方向上的步数,然后就是最短路的事情了

推荐使用dijkstra算法,能够保证在$O(qn^2logn^2)$内算出..

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <cstdlib>
  4. #include <algorithm>
  5. #include <queue>
  6. using namespace std;
  7. const int dx[4] = { 0, 1, -1, 0 };
  8. const int dy[4] = { 1, 0, 0, -1 };
  9. const int inf = 0x7fffffff;
  10. int f[35][35][4][4], num[35][35][4], tot;
  11. int dis[4010];
  12. bool v[35][35];
  13. int n, m, q;
  14. int dist[35][35]; bool bo[35][35];
  15. struct zb {
  16. int x, y;
  17. }e, s, t;
  18. void bfs1 ( int xx, int yy, int k ){
  19. queue <zb> q;
  20. for ( int i = 0; i <= n+1; i ++ ) for ( int j = 0; j <= m+1; j ++ ) dist[i][j] = inf, bo[i][j] = false;
  21. zb x;
  22. x.x = xx+dx[k]; x.y = yy+dy[k];
  23. q.push (x);
  24. dist[x.x][x.y] = 0; bo[x.x][x.y] = true;
  25. while ( !q.empty () ){
  26. x = q.front (); q.pop ();
  27. for ( int i = 0; i < 4; i ++ ){
  28. zb y;
  29. y.x = x.x+dx[i]; y.y = x.y+dy[i];
  30. if ( v[y.x][y.y] == false || bo[y.x][y.y] == true ) continue;
  31. dist[y.x][y.y] = dist[x.x][x.y]+1;
  32. bo[y.x][y.y] = true;
  33. q.push (y);
  34. }
  35. }
  36. for ( int i = 0; i < 4; i ++ ){
  37. f[xx][yy][k][i] = dist[xx+dx[i]][yy+dy[i]];
  38. }
  39. }
  40. void bfs2 (){
  41. queue <zb> q;
  42. for ( int i = 0; i <= n+1; i ++ ) for ( int j = 0; j <= m+1; j ++ ) dist[i][j] = inf, bo[i][j] = false;
  43. q.push (e);
  44. dist[e.x][e.y] = 0; bo[e.x][e.y] = true;
  45. while ( !q.empty () ){
  46. zb x = q.front (); q.pop ();
  47. for ( int i = 0; i < 4; i ++ ){
  48. zb y;
  49. y.x = x.x+dx[i]; y.y = x.y+dy[i];
  50. if ( v[y.x][y.y] == false || bo[y.x][y.y] == true ) continue;
  51. dist[y.x][y.y] = dist[x.x][x.y]+1;
  52. bo[y.x][y.y] = true;
  53. q.push (y);
  54. }
  55. }
  56. }
  57. struct node {
  58. int y, next, d;
  59. }a[160010]; int first[4010], len;
  60. void ins ( int x, int y, int d ){
  61. len ++;
  62. a[len].y = y; a[len].d = d;
  63. a[len].next = first[x]; first[x] = len;
  64. }
  65. struct knode {
  66. int x, dis;
  67. };
  68. bool operator < ( knode x, knode y ){ return x.dis > y.dis; }
  69. priority_queue <knode> Q;
  70. void dij (){
  71. while ( !Q.empty () ){
  72. knode x = Q.top (); Q.pop ();
  73. if ( dis[x.x] < x.dis ) continue;
  74. for ( int k = first[x.x]; k; k = a[k].next ){
  75. int y = a[k].y;
  76. if ( dis[y] > dis[x.x]+a[k].d ){
  77. dis[y] = dis[x.x]+a[k].d;
  78. knode p;
  79. p.x = y; p.dis = dis[y];
  80. Q.push (p);
  81. }
  82. }
  83. }
  84. }
  85. int _min ( int x, int y ){ return x < y ? x : y; }
  86. int main (){
  87. int i, j, k;
  88. scanf ( "%d%d%d", &n, &m, &q );
  89. for ( i = 1; i <= n; i ++ ){
  90. for ( j = 1; j <= m; j ++ ){
  91. int x;
  92. scanf ( "%d", &x );
  93. if ( x == 1 ) v[i][j] = true;
  94. }
  95. }
  96. tot = 0;
  97. for ( i = 1; i <= n; i ++ ){
  98. for ( j = 1; j <= m; j ++ ){
  99. if ( v[i][j] == false ) continue;
  100. for ( k = 0; k < 4; k ++ ){
  101. if ( v[i+dx[k]][j+dy[k]] == true ){
  102. v[i][j] = false;
  103. bfs1 ( i, j, k );
  104. v[i][j] = true;
  105. num[i][j][k] = ++tot;
  106. }
  107. else for ( int l = 0; l < 4; l ++ ) f[i][j][k][l] = inf;
  108. }
  109. }
  110. }
  111. while ( q -- ){
  112. scanf ( "%d%d%d%d%d%d", &e.x, &e.y, &s.x, &s.y, &t.x, &t.y );
  113. if ( s.x == t.x && s.y == t.y ){ printf ( "0\n" ); continue; }
  114. v[s.x][s.y] = false;
  115. bfs2 ();
  116. v[s.x][s.y] = true;
  117. for ( j = 1; j <= tot; j ++ ) first[j] = 0, dis[j] = inf;
  118. len = 0;
  119. for ( j = 0; j < 4; j ++ ){
  120. if ( dist[s.x+dx[j]][s.y+dy[j]] != inf ){
  121. knode p;
  122. p.x = num[s.x][s.y][j]; p.dis = dist[s.x+dx[j]][s.y+dy[j]];
  123. Q.push (p);
  124. dis[num[s.x][s.y][j]] = dist[s.x+dx[j]][s.y+dy[j]];
  125. }
  126. }
  127. for ( i = 1; i <= n; i ++ ){
  128. for ( j = 1; j <= m; j ++ ){
  129. for ( k = 0; k < 4; k ++ ){
  130. if ( v[i+dx[k]][j+dy[k]] == true ){
  131. for ( int l = 0; l < 4; l ++ ){
  132. if ( f[i][j][k][l] != inf ) ins ( num[i][j][k], num[i][j][l], f[i][j][k][l] );
  133. }
  134. ins ( num[i][j][k], num[i+dx[k]][j+dy[k]][3-k], 1 );
  135. }
  136. }
  137. }
  138. }
  139. dij ();
  140. int ans = inf;
  141. for ( i = 0; i < 4; i ++ ){
  142. if ( num[t.x][t.y][i] != 0 ) ans = _min ( ans, dis[num[t.x][t.y][i]] );
  143. }
  144. if ( ans != inf ) printf ( "%d\n", ans );
  145. else printf ( "-1\n" );
  146. }
  147. return 0;
  148. }

  


noip2011 选择客栈

一开始看错题了.. 做法其实没啥区别就是强行解释一下

由于题目给出的$p$是不会变的,然后就可以瞎搞处理了,时间复杂度是$O(k*小于等于p的节点数)$

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <cstdlib>
  4. #include <algorithm>
  5. using namespace std;
  6. const int Maxc = 55;
  7. int c[Maxc], ans[Maxc];
  8. int n, K, p;
  9. int main (){
  10. int i, j, k;
  11. scanf ( "%d%d%d", &n, &K, &p );
  12. int anss = 0;
  13. for ( i = 1; i <= n; i ++ ){
  14. int fl, x;
  15. scanf ( "%d%d", &fl, &x );
  16. c[fl] ++;
  17. if ( x <= p ){
  18. for ( j = 0; j < K; j ++ ) ans[j] = c[j];
  19. }
  20. anss += ans[fl];
  21. if ( x <= p ) anss --;
  22. }
  23. printf ( "%d\n", anss );
  24. return 0;
  25. }

  


noip2012 开车旅行

由于两人决策唯一性,那么可以预处理出从某点开始走$2^i$步到达的点..

讲道理的话其实也就只需要处理$f_{i,0}$和$f_{i,1}$,后面的都可以倍增求

第一问就枚举点倍增搞

其他问就直接跑..

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <cstdlib>
  4. #include <algorithm>
  5. #include <set>
  6. #define LL long long
  7. using namespace std;
  8. const int Maxn = 100010;
  9. const int inf = 0x7fffffff;
  10. struct no {
  11. int x, h;
  12. };
  13. bool operator < ( no x, no y ){ return x.h < y.h; }
  14. set <no> S;
  15. set <no> :: iterator it;
  16. int h[Maxn], n, m;
  17. int fa[Maxn][22], fb[Maxn][22], f[Maxn][22];
  18. no gob[Maxn];
  19. void pre (){
  20. int i, j, k;
  21. no p;
  22. p.x = n; p.h = h[n];
  23. S.insert (p);
  24. for ( i = n-1; i >= 1; i -- ){
  25. p.x = i; p.h = h[i];
  26. it = S.lower_bound (p);
  27. no fir, sec;
  28. fir.h = inf; sec.h = inf;
  29. if ( it != S.end () ){
  30. fir.x = (*it).x; fir.h = (*it).h-h[i];
  31. it ++;
  32. if ( it != S.end () ) sec.x = (*it).x, sec.h = (*it).h-h[i];
  33. it --;
  34. }
  35. if ( it != S.begin () ){
  36. it --;
  37. if ( h[i]-(*it).h <= fir.h ){
  38. sec = fir;
  39. fir.x = (*it).x; fir.h = h[i]-(*it).h;
  40. }
  41. else if ( h[i]-(*it).h <= sec.h ){
  42. sec.x = (*it).x; sec.h = h[i]-(*it).h;
  43. }
  44. if ( it != S.begin () ){
  45. it --;
  46. if ( h[i]-(*it).h <= sec.h ){
  47. sec.x = (*it).x; sec.h = h[i]-(*it).h;
  48. }
  49. }
  50. }
  51. if ( sec.h != inf ){
  52. f[i][0] = sec.x; f[i][1] = gob[sec.x].x;
  53. fa[i][0] = fa[i][1] = sec.h;
  54. fb[i][0] = 0; fb[i][1] = gob[sec.x].h;
  55. for ( j = 2; j <= 21 && i+(1<<(j-1)) <= n; j ++ ){
  56. f[i][j] = f[f[i][j-1]][j-1];
  57. fa[i][j] = fa[i][j-1] + fa[f[i][j-1]][j-1];
  58. fb[i][j] = fb[i][j-1] + fb[f[i][j-1]][j-1];
  59. }
  60. }
  61. if ( fir.h != inf ) gob[i] = fir;
  62. S.insert (p);
  63. }
  64. }
  65. struct node {
  66. int na, nb;
  67. };
  68. void gogogo ( int st, int xx, node &jl ){
  69. jl.na = jl.nb = 0;
  70. int i;
  71. for ( i = 21; i >= 0; i -- ){
  72. if ( fa[st][i]+fb[st][i] <= xx && f[st][i] != 0 ){
  73. jl.na += fa[st][i];
  74. jl.nb += fb[st][i];
  75. xx -= fa[st][i]+fb[st][i];
  76. st = f[st][i];
  77. }
  78. }
  79. }
  80. int main (){
  81. int i, j, k;
  82. scanf ( "%d", &n );
  83. for ( i = 1; i <= n; i ++ ) scanf ( "%d", &h[i] );
  84. pre ();
  85. int x0, s0;
  86. scanf ( "%d", &x0 );
  87. s0 = n; node ans, po;
  88. ans.na = ans.nb = 0;
  89. for ( i = n-1; i >= 1; i -- ){
  90. gogogo ( i, x0, po );
  91. if ( (LL)po.na*ans.nb < (LL)ans.na*po.nb || ( (LL)po.na*ans.nb == (LL)ans.na*po.nb && h[i] > h[s0] ) || s0 == n || ( ans.nb == 0 && po.nb != 0 ) ){
  92. s0 = i;
  93. ans = po;
  94. }
  95. }
  96. printf ( "%d\n", s0 );
  97. scanf ( "%d", &m );
  98. for ( i = 1; i <= m; i ++ ){
  99. int ss, xx;
  100. scanf ( "%d%d", &ss, &xx );
  101. gogogo ( ss, xx, po );
  102. printf ( "%d %d\n", po.na, po.nb );
  103. }
  104. return 0;
  105. }

  


noip2011 观光公交

记录$time_i$是到达$i$点的最小时刻,$last_i$是最迟一个到达$i$点的人的时刻

那么$time_i=\max(time_{i-1},last_{i-1})+d_i$

可以处理出修改每一个$d_i$所影响的人数

每次贪心找一个最大的减去就好了

时间复杂度是$O(nk)$的..

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <cstdlib>
  4. #include <algorithm>
  5. using namespace std;
  6. const int Maxn = 100010;
  7. int time[Maxn], d[Maxn], last[Maxn];
  8. int n, m, K;
  9. struct lnode {
  10. int st, ed, t;
  11. }list[Maxn];
  12. int sum[Maxn], f[Maxn];
  13. int _max ( int x, int y ){ return x > y ? x : y; }
  14. int main (){
  15. int i, j, k;
  16. scanf ( "%d%d%d", &n, &m, &K );
  17. for ( i = 2; i <= n; i ++ ) scanf ( "%d", &d[i] );
  18. for ( i = 1; i <= m; i ++ ){
  19. scanf ( "%d%d%d", &list[i].t, &list[i].st, &list[i].ed );
  20. last[list[i].st] = _max ( last[list[i].st], list[i].t );
  21. sum[list[i].ed] ++;
  22. }
  23. time[1] = 0;
  24. for ( i = 2; i <= n; i ++ ){
  25. time[i] = _max ( time[i-1], last[i-1] ) + d[i];
  26. sum[i] += sum[i-1];
  27. }
  28. int ans = 0;
  29. for ( i = 1; i <= m; i ++ ){
  30. ans += time[list[i].ed] - list[i].t;
  31. }
  32. while ( K -- ){
  33. f[n] = n;
  34. for ( i = n-1; i >= 2; i -- ){
  35. if ( time[i] > last[i] ) f[i] = f[i+1];
  36. else f[i] = i;
  37. }
  38. int Max = 0, p;
  39. for ( i = 2; i <= n; i ++ ){
  40. if ( sum[f[i]]-sum[i-1] > Max && d[i] > 0 ){
  41. Max = sum[f[i]]-sum[i-1];
  42. p = i;
  43. }
  44. }
  45. ans -= Max; d[p] --;
  46. for ( i = 2; i <= n; i ++ ){
  47. time[i] = _max ( time[i-1], last[i-1] ) + d[i];
  48. }
  49. }
  50. printf ( "%d\n", ans );
  51. return 0;
  52. }

  


历年NOIP水题泛做的更多相关文章

  1. Atcoder 水题选做

    为什么是水题选做呢?因为我只会水题啊 ( 为什么是$Atcoder$呢?因为暑假学长来讲课的时候讲了三件事:不要用洛谷,不要用dev-c++,不要用单步调试.$bzoj$太难了,$Topcoder$整 ...

  2. 历年NOIP真题总结

    前言:最近把历年的NOIP真题肝了一遍(还有3个紫题先咕掉了),主要是到1998年的提高组的题.把题目的做题简要思路搁在这儿,一个是为了考前翻一翻,想想自己的哪些思路要梳理的什么什么的,反正怎么说呢, ...

  3. NOIP水题测试(2017082501)

    日常水题测试又来了! 以后答案都以单题形式公布. 下面看今天的水题: 时间限制:5小时 题目一:无法形容的水 题目二:比上一题还水 题目三:一元三次方程求解 题目四:单词接龙 题目五:统计单词个数 题 ...

  4. NOIP水题测试(2017082401)

    哈,水题测试又来了! 上次的水题简单吧! 答案是以单题形式发布的(旅行家的预算随后发布). 下面来看今天的题,还是水题. 时间限制:5小时 题目一:看上去就很水 题目二:比上面一题还水 题目三:数的划 ...

  5. 失踪的7(P1590&NOIP水题测试(2017082301))

    题目链接:失踪的7 水题,不解释. #include<bits/stdc++.h> using namespace std; int main(){ int t; scanf(" ...

  6. 子数整数(P1151&NOIP水题测试(2017082301))

    题目链接:子数整数 水题,不解释,自己看代码: #include<bits/stdc++.h> using namespace std; int main(){ int k; scanf( ...

  7. NOIP水题合集[3/未完待续]

    NOIP2008pj传球游戏 题目描述 上体育课的时候,小蛮的老师经常带着同学们一起做游戏.这次,老师带着同学们一起做传球游戏. 游戏规则是这样的:n个同学站成一个圆圈,其中的一个同学手里拿着一个球, ...

  8. LCT裸题泛做

    ①洞穴勘测 bzoj2049 题意:由若干个操作,每次加入/删除两点间的一条边,询问某两点是否连通.保证任意时刻图都是一个森林.(两点之间至多只有一条路径) 这就是个link+cut+find roo ...

  9. NOIP水题测试(2017082301)

    你们从题目也能看出来今天的题是很水的. 前几期答案还没出,效率有点低,谅解,谅解. 今天的答案应该会出的很快. 下面给题目: 时间限制:3小时 题目一:旅行家的预算 题目二:进制转换 题目三:乘积最大 ...

随机推荐

  1. 导出Excel通用工具类

    导出Excel的两种方法: 一,POI 导入poi包 poi-3.11-beta3-20141111.jar /** * */ package com.car.ots.mpckp.utils; imp ...

  2. MySQL复制和集群

    一.复制配置 (A) 主从服务器相同版本的数据库 (B) 主服务器上复制使用的账户,具有相应的权限. (C) 修改主服务器的配置文件my.cnf,开启BINLOG,并设置server-id的值.重启后 ...

  3. bzoj4692: Beautiful Spacing

    先二分答案后dp 设\(su[n]\)为\(\sum_{1}^{n}xi[i]\) 设\(f[n]\)为1时表示第n个单次能做某一行的结尾,且之前的空格满足二分出来的答案. 考虑怎样的\(f[i]\) ...

  4. paxos(chubby) vs zab(Zookeeper)

    参考: Zookeeper的一致性协议:Zab Chubby&Zookeeper原理及在分布式环境中的应用 Paxos vs. Viewstamped Replication vs. Zab ...

  5. Angular2 表单

    1. 说明 表单是Web程序中的重要组成部分,构建良好以及实用的表单必须解决如下几个问题: (1). 如何跟踪及更新表单的数据状态 (2). 如何进行表单验证 (3). 如何显示表单验证信息 Angu ...

  6. 按钮button的css样式(扁平化底色)

    .button { background-color: #ff0000; /* Green */ border: none; color: white; font-family:Arial; padd ...

  7. JSTL 操作符

    el表达式的取值默认顺序:     pageScope  requestScope  sessionScope  applicationScope     结构,采用.导航,也称为存取器   ${us ...

  8. 八款常见的Android游戏引擎

    原文地址:http://bbs.csdn.net/topics/380203732 1.Angle  Angle是一款专为Android平台设计的,敏捷且适合快速开发的2D游戏引擎,基于OpenGL  ...

  9. mina中游戏客户端服务端数据交互流程

    ====================================================================================CLIENT    encode ...

  10. 破解myEclipse

    建立一个java项目,将reg.java放入,并且运行在控制台 输入账户 回车就会出现 序列号 菜单栏--->myeclipse-->substription information--- ...