瞎扯

  又来打比赛了,发现自己菜得不行。

  果然我是标准的普及组选手。(这个队名是啥意思?我也不知道,因为不知道取啥队名,就随机在键盘上敲Emmm)

  这次队友很给力,把我不会的模拟和贪心全切掉了,并且每次翻译了正确的题意(我英语真垃圾)。(上次UESTC ACM Final的队友让我很绝望,既不会做题又给我翻译假题面)

  然后我把剩下的送分题都切掉了。

  于是被碾压了:

  开始通读全题(提供pdf真良心,避免网卡耽误时间),我觉得很绝望,尤其是那个B,读得我很绝望,直接扔翻译里都弃了。

  之后并不知道怎么做题,然后随机一道题,发现是水题是一道水题就直接切掉了。

  之后就开始看榜,那个题通过的队多就做哪个。

  佬表示这个不是正确的做法,正确的做法是每个人随机若干道题,先自己去做,不会的话然后扔给队友。

  挂掉的话也可以扔队友。

  但是我和我队友都挺菜的,这么搞可能完蛋了。

  下来发现B,J都是送分题。

Problem A Find a Number

题目大意

  问最小的满足各位数字之和为$s$并且能被$d$整除的正整数。

  首先用bfs确定它的位数,每个状态记录通过尽量小的转移边转移的前驱。

  然后做完了。

Code

  1. /**
  2. * Codeforces
  3. * Problem#1070A
  4. * Accepted
  5. * Time: 108ms
  6. * Memory: 24800k
  7. * Author: yyf
  8. */
  9. #include <iostream>
  10. #include <cstdlib>
  11. #include <cstring>
  12. #include <cstdio>
  13. #include <queue>
  14. using namespace std;
  15. typedef bool boolean;
  16.  
  17. const int N = , D = ;
  18. #define pii pair<int, int>
  19. #define fi first
  20. #define sc second
  21.  
  22. int d, s;
  23. int f[N][D];
  24. char lst[N][D];
  25. int lstr[N][D];
  26. boolean vis[N][D];
  27.  
  28. pii trans(int s, int r, int dig) {
  29. return pii(s + dig, (r * + dig) % d);
  30. }
  31.  
  32. inline void init() {
  33. scanf("%d%d", &d, &s);
  34. }
  35.  
  36. queue<pii> que;
  37. boolean bfs() {
  38. que.push(pii(, ));
  39. memset(f, 0x3f, sizeof(f));
  40. f[][] = , vis[][] = true;
  41. while (!que.empty()) {
  42. pii e = que.front();
  43. que.pop();
  44.  
  45. for (int i = ; i <= ; i++) {
  46. pii eu = trans(e.fi, e.sc, i);
  47. if (eu.fi > s)
  48. break;
  49. if (vis[eu.fi][eu.sc])
  50. continue;
  51. vis[eu.fi][eu.sc] = true;
  52. lst[eu.fi][eu.sc] = i + '';
  53. lstr[eu.fi][eu.sc] = e.sc;
  54. f[eu.fi][eu.sc] = f[e.fi][e.sc] + ;
  55. que.push(eu);
  56. }
  57. }
  58. return vis[s][];
  59. }
  60.  
  61. void print(int s, int r) {
  62. if (!s && !r)
  63. return ;
  64. int nr = lstr[s][r];
  65. print(s - lst[s][r] + '', nr);
  66. putchar(lst[s][r]);
  67. }
  68.  
  69. inline void solve() {
  70. if (bfs()) {
  71. print(s, );
  72. } else
  73. puts("-1");
  74. }
  75.  
  76. int main() {
  77. init();
  78. solve();
  79. return ;
  80. }

Problem A

Problem B Berkomnadzor

题目大意

  给定一个IPv4白名单和黑名单,要求用最少的IPv4码给出一个包含所有黑名单中的地址但不包含任何一个白名单里的地址。

  先判掉无解的情况。

  剩下直接分治。

Code

  1. /**
  2. * Codeforces
  3. * Problem#1070B
  4. * Accepted
  5. * Time: 530ms
  6. * Memory: 52800k
  7. */
  8. #include <bits/stdc++.h>
  9. using namespace std;
  10. typedef bool boolean;
  11.  
  12. #define ull unsigned long long
  13. #define pii pair<int, int>
  14. #define ll long long
  15. #define ui unsigned
  16. #define sc second
  17. #define fi first
  18.  
  19. const signed ll llf = (signed ll) (~0ull >> );
  20. const signed int inf = (signed) (~0u >> );
  21.  
  22. template <typename T>
  23. T __abs(T x) {
  24. return (x < ) ? (-x) : (x);
  25. }
  26.  
  27. template <typename T>
  28. void pfill(T* pst, const T* ped, T val) {
  29. for ( ; pst != ped; *(pst++) = val);
  30. }
  31.  
  32. template <typename T>
  33. void pcopy(T* pst, const T* ped, T* pv) {
  34. for ( ; pst != ped; *(pst++) = *(pv++));
  35. }
  36.  
  37. #define digit(_x) ((_x) >= '0' && (_x) <= '9')
  38.  
  39. template <typename T>
  40. char* read(char* s, T& u) {
  41. for ( ; *s && !digit(*s); s++);
  42. if (!*s)
  43. return NULL;
  44. for (u = *s - ''; ++s, digit(*s); u = u * + *s - '');
  45. return s;
  46. }
  47.  
  48. const int N = 2e5 + ;
  49.  
  50. typedef class Segment {
  51. public:
  52. ui l, r;
  53. ui sgn;
  54.  
  55. Segment() { }
  56. Segment(ui l, ui r, ui sgn):l(l), r(r), sgn(sgn) { }
  57.  
  58. boolean operator < (Segment b) const {
  59. if (l ^ b.l)
  60. return l < b.l;
  61. return r < b.r;
  62. }
  63.  
  64. boolean intersect(Segment b) {
  65. return !(b.r < l || b.l > r);
  66. }
  67. }Segment;
  68.  
  69. int n;
  70. char buf[];
  71.  
  72. Segment read() {
  73. ui l, r, x;
  74. scanf("%s", buf);
  75. ui sgn = (buf[] == '+');
  76. char* str = buf + ;
  77. str = read(str, l);
  78. str = read(str, x), l = l << | x;
  79. str = read(str, x), l = l << | x;
  80. str = read(str, x), l = l << | x;
  81. if (*str == '/') {
  82. read(str, x);
  83. x = - x;
  84. l >>= x, l <<= x;
  85. if (x == )
  86. r = ~0u;
  87. else
  88. r = l | (( << x) - );
  89. return Segment(l, r, sgn);
  90. }
  91. return Segment(l, l, sgn);
  92. }
  93.  
  94. int res = ;
  95. vector<Segment> ss, rs;
  96.  
  97. inline void init() {
  98. scanf("%d", &n);
  99. Segment s;
  100. for (int i = ; i <= n; i++)
  101. s = read(), ss.push_back(s);
  102. }
  103.  
  104. void dividing(vector<Segment> &ss, ui l, ui r, ui bit) {
  105. if (ss.empty())
  106. return;
  107. boolean app1 = false, app0 = false;
  108. for (ui i = ; i < ss.size(); i++)
  109. app1 |= (ss[i].sgn == ), app0 |= (ss[i].sgn == );
  110.  
  111. if (!app1) {
  112. rs.push_back(Segment(l, - bit, ));
  113. return;
  114. }
  115.  
  116. if (!app0)
  117. return;
  118.  
  119. assert(l ^ r);
  120.  
  121. ui mid = l + ((r - l) >> );
  122. vector<Segment> ql, qr;
  123. for (ui i = ; i < ss.size(); i++) {
  124. if (ss[i].r <= mid)
  125. ql.push_back(ss[i]);
  126. else if (ss[i].l > mid)
  127. qr.push_back(ss[i]);
  128. else {
  129. ql.push_back(Segment(ss[i].l, mid, ss[i].sgn));
  130. qr.push_back(Segment(mid + , ss[i].r, ss[i].sgn));
  131. }
  132. }
  133. ss.clear();
  134. dividing(ql, l, mid, bit - );
  135. dividing(qr, mid + , r, bit - );
  136. }
  137.  
  138. inline void solve() {
  139. sort(ss.begin(), ss.end());
  140. for (ui i = , j; i < ss.size(); i = j)
  141. for (j = i + ; j < ss.size() && ss[j].intersect(ss[i]); j++)
  142. if (ss[j].sgn ^ ss[i].sgn) {
  143. puts("-1");
  144. return;
  145. }
  146. dividing(ss, , ~0u, );
  147. printf("%u\n", rs.size());
  148. ui msk = ( << ) - ;
  149. for (ui i = , x; i < rs.size(); i++) {
  150. x = rs[i].l;
  151. printf("%u.%u.%u.%u/%u\n", x >> , x >> & msk, x >> & msk, x & msk, rs[i].r);
  152. }
  153. }
  154.  
  155. int main() {
  156. init();
  157. solve();
  158. return ;
  159. }

Problem B

Problem C Cloud Computing

题目大意

  一个公司每天需要$K$个CPU内核,有$m$个供应商,在第$l_i$到第$r_i$天,以每个CPU内核$p_i$的价格提供$c_i$个,如果一天买不够,那么必须把能够提供的内核都购买。问最小的总花费。

  随便拿个数据结构就过了。

Code

  1. /**
  2. * Codeforces
  3. * Problem#1070C
  4. * Accepted
  5. * Time: 249ms
  6. * Memory: 28000k
  7. * Author: yyf
  8. */
  9. #include <algorithm>
  10. #include <iostream>
  11. #include <cstring>
  12. #include <cstdlib>
  13. #include <cstdio>
  14. #include <vector>
  15. using namespace std;
  16. typedef bool boolean;
  17.  
  18. typedef class Opt {
  19. public:
  20. int i, p, c;
  21. int sgn;
  22.  
  23. Opt(int i, int p, int c, int sgn):i(i), p(p), c(c), sgn(sgn) { }
  24.  
  25. boolean operator < (Opt b) const {
  26. return i < b.i;
  27. }
  28. }Opt;
  29.  
  30. const int bzmax = ;
  31.  
  32. template <typename T>
  33. class IndexedTree {
  34. public:
  35. int s;
  36. T* ar;
  37.  
  38. IndexedTree() { }
  39. IndexedTree(int s):s(s) {
  40. ar = new T[(s + )];
  41. memset(ar, , sizeof(T) * (s + ));
  42. }
  43.  
  44. void add(int idx, T val) {
  45. for ( ; idx <= s; idx += (idx & (-idx)))
  46. ar[idx] += val;
  47. }
  48.  
  49. T query(int idx) {
  50. T rt = ;
  51. for ( ; idx; idx -= (idx & (-idx)))
  52. rt += ar[idx];
  53. return rt;
  54. }
  55.  
  56. int kth(int k) {
  57. int rt = , cur = ;
  58. for (int l = ( << (bzmax - )); l; l >>= )
  59. if ((rt | l) <= s && (cur + ar[rt | l]) < k)
  60. rt |= l, cur += ar[rt];
  61. return rt + ;
  62. }
  63. };
  64.  
  65. #define ll long long
  66.  
  67. const int V = 1e6 + ;
  68.  
  69. int n, K, m;
  70. IndexedTree<ll> itc;
  71. IndexedTree<ll> its;
  72. vector<Opt> vs;
  73.  
  74. inline void init() {
  75. scanf("%d%d%d", &n, &K, &m);
  76. itc = IndexedTree<ll>(V);
  77. its = IndexedTree<ll>(V);
  78. for (int i = , l, r, c, p; i <= m; i++) {
  79. scanf("%d%d%d%d", &l, &r, &c, &p);
  80. vs.push_back(Opt(l, p, c, ));
  81. vs.push_back(Opt(r + , p, c, -));
  82. }
  83. }
  84.  
  85. ll res = ;
  86. inline void solve() {
  87. sort(vs.begin(), vs.end());
  88. int pv = , s = (signed) vs.size();
  89. for (int i = ; i <= n; i++) {
  90. while (pv < s && vs[pv].i == i) {
  91. itc.add(vs[pv].p, vs[pv].c * vs[pv].sgn);
  92. its.add(vs[pv].p, vs[pv].c * 1ll * vs[pv].p * vs[pv].sgn);
  93. pv++;
  94. }
  95. ll cnt = itc.query(V);
  96. if (cnt < K) {
  97. res += its.query(V);
  98. } else {
  99. int p = itc.kth(K);
  100. cnt = itc.query(p);
  101. res += its.query(p) - (cnt - K) * p;
  102. }
  103. }
  104. cout << res << endl;
  105. }
  106.  
  107. int main() {
  108. init();
  109. solve();
  110. return ;
  111. }

Problem C

Problem D Garbage Disposal

题目大意

  每天会产生若干垃圾,每天的垃圾只能当天或者后天处理,第$n + 1$天不能留下垃圾。每次处理垃圾至多能处理$k$个单位,问最少的总处理次数。

  随便模拟一下就过了。

Code

  1. //Author: dream_maker
  2. #include<bits/stdc++.h>
  3. using namespace std;
  4. //----------------------------------------------
  5. //typename
  6. typedef long long ll;
  7. //convenient for
  8. #define fu(a, b, c) for (int a = b; a <= c; ++a)
  9. #define fd(a, b, c) for (int a = b; a >= c; --a)
  10. #define fv(a, b) for (int a = 0; a < (signed)b.size(); ++a)
  11. //inf of different typename
  12. const int INF_of_int = 1e9;
  13. const ll INF_of_ll = 1e18;
  14. //fast read and write
  15. template <typename T>
  16. void Read(T &x) {
  17. bool w = ;x = ;
  18. char c = getchar();
  19. while (!isdigit(c) && c != '-') c = getchar();
  20. if (c == '-') w = , c = getchar();
  21. while (isdigit(c)) {
  22. x = (x<<) + (x<<) + c -'';
  23. c = getchar();
  24. }
  25. if (!w) x = -x;
  26. }
  27. template <typename T>
  28. void Write(T x) {
  29. if (x < ) {
  30. putchar('-');
  31. x = -x;
  32. }
  33. if (x > ) Write(x / );
  34. putchar(x % + '');
  35. }
  36. //----------------------------------------------
  37. const int N = 3e5 + ;
  38. ll a[N], n, k, ans = ;
  39. int main() {
  40. Read(n), Read(k);
  41. fu(i, , n) Read(a[i]);
  42. fu(i, , n - ) {
  43. if (!a[i]) continue;
  44. ll num = a[i] / k;
  45. if (a[i] % k) ++num;
  46. a[i + ] = max(0ll, a[i + ] - (num * k - a[i]));
  47. ans += num;
  48. }
  49. if (a[n]) {
  50. ans += a[n] / k;
  51. if (a[n] % k) ++ans;
  52. }
  53. Write(ans);
  54. return ;
  55. }

Problem D

Problem E Getting Deals Done

题目大意

  有$n$个任务和参数$m$,每个任务有一个耗时$p_i$,以及时限$t$,要求出$d$使得按照下面方式完成的任务尽量多。

  1. 按顺序完成$p_i \leqslant d$的任务
  2. 每做$m$个任务需要休息与做这$m$个任务花费的时间相等的时间。

  yangkai觉得这玩意儿可以三分,于是我们成功得到了-5.

  发现有用的$d$一定时某个$p_i$,可以把$p_i$排序,按顺序插进树状数组。

  每次可以二分一下求出能够完成的任务的数量。

  时间复杂度$O(n\log^{2} n)$。

  但是这个可以二分答案。

  判断条件是是否能够把所有可做的任务做完。

  答案只可能是它或者它加上1后的情况,

  因为再大的时候不会花更少的时间去做数量相同的任务。

  然后我的垃圾做法就被暴打了。

  然后注意几个地方:

  1. $p$相同的任务要一起加入树状数组
  2. 树状数组求第$k$大特判$k = 0$。

  继续口胡一个做法,考虑按顺序枚举序列,同时对所有 $d$ 维护当前花费的时间以及完成的任务数,超时的总是 $d$ 最大的几个,用一个变量维护当前最大的没有超时的 $d$,check 它是否超时可以再开 2 个 BIT。

Code

  1. /**
  2. * Codeforces
  3. * Problem#1070E
  4. * Accepted
  5. * Time: 608ms
  6. * Memory: 4700k
  7. */
  8. #include <algorithm>
  9. #include <iostream>
  10. #include <cstring>
  11. #include <cstdlib>
  12. #include <cstdio>
  13. #ifndef WIN32
  14. #define Auto "%lld"
  15. #else
  16. #define Auto "%I64d"
  17. #endif
  18. using namespace std;
  19. typedef bool boolean;
  20. #define ll long long
  21.  
  22. template <typename T>
  23. class IndexedTree {
  24. public:
  25. int s;
  26. T* ar;
  27.  
  28. IndexedTree() { }
  29. IndexedTree(int s):s(s) {
  30. ar = new T[(s + )];
  31. memset(ar, , sizeof(T) * (s + ));
  32. }
  33.  
  34. void add(int idx, T val) {
  35. for ( ; idx <= s; idx += (idx & (-idx)))
  36. ar[idx] += val;
  37. }
  38.  
  39. T query(int idx) {
  40. T rt = ;
  41. for ( ; idx; idx -= (idx & (-idx)))
  42. rt += ar[idx];
  43. return rt;
  44. }
  45.  
  46. int kth(int k) {
  47. if (!k)
  48. return ;
  49. int rt = , cur = ;
  50. for (int i = ( << ); i; i >>= )
  51. if ((rt | i) <= s && ar[rt | i] + cur < k)
  52. rt |= i, cur += ar[rt];
  53. return rt + ;
  54. }
  55.  
  56. void clear() {
  57. s = ;
  58. delete[] ar;
  59. }
  60. };
  61.  
  62. const int N = 2e5 + ;
  63. #define pii pair<int, int>
  64. #define fi first
  65. #define sc second
  66.  
  67. int T;
  68. int n, m;
  69. ll t;
  70. IndexedTree<int> itc;
  71. IndexedTree<ll> its;
  72. int ps[N];
  73. pii ar[N];
  74.  
  75. inline void init() {
  76. scanf("%d%d"Auto, &n, &m, &t);
  77. itc = IndexedTree<int>(n);
  78. its = IndexedTree<ll>(n);
  79. for (int i = ; i <= n; i++)
  80. scanf("%d", ps + i), ar[i] = pii(ps[i], i);
  81. }
  82.  
  83. int query(int i) {
  84. int l = , r = i, mid, k, ti;
  85. ll s = ;
  86. while (l <= r) {
  87. mid = (l + r) >> ;
  88. k = itc.kth(mid);
  89. s = its.query(k);
  90. ti = (mid - ) / m * m;
  91. k = itc.kth(ti);
  92. s += its.query(k);
  93. if (s > t)
  94. r = mid - ;
  95. else
  96. l = mid + ;
  97. }
  98. return l - ;
  99. }
  100.  
  101. inline void solve() {
  102. int ansc = , ansd = ;
  103. sort(ar + , ar + n + );
  104. int i = , c;
  105. while (i <= n) {
  106. int cur = ar[i].fi;
  107. while (i <= n && ar[i].fi == cur) {
  108. itc.add(ar[i].sc, );
  109. its.add(ar[i].sc, ar[i].fi);
  110. i++;
  111. }
  112. c = query(i - );
  113. if (c > ansc)
  114. ansc = c, ansd = ar[i - ].fi;
  115. }
  116. printf("%d %d\n", ansc, ansd);
  117. }
  118.  
  119. void clear() {
  120. itc.clear();
  121. its.clear();
  122. }
  123.  
  124. int main() {
  125. scanf("%d", &T);
  126. while (T--) {
  127. init();
  128. solve();
  129. clear();
  130. }
  131. return ;
  132. }

Problem E

Problem F Debate

题目大意

  有$n$个观众,每个观众有一个观点是否支持$Alice$以及支持$Bob$,和一个影响度。

  要求选出一些人使得至少有一半的人支持$Alice$和一半的人支持$Bob$,最大化他们的影响度之和。

  两者都支持的一定全选。

  然后支持一方的配对选。

  剩下的再怎么选都不会改变还能选多少人,直接贪。

Code

  1. //Author: dream_maker
  2. #include<bits/stdc++.h>
  3. using namespace std;
  4. //----------------------------------------------
  5. //typename
  6. typedef long long ll;
  7. //convenient for
  8. #define fu(a, b, c) for (int a = b; a <= c; ++a)
  9. #define fd(a, b, c) for (int a = b; a >= c; --a)
  10. #define fv(a, b) for (int a = 0; a < (signed)b.size(); ++a)
  11. //inf of different typename
  12. const int INF_of_int = 1e9;
  13. const ll INF_of_ll = 1e18;
  14. //fast read and write
  15. template <typename T>
  16. void Read(T &x) {
  17. bool w = ;x = ;
  18. char c = getchar();
  19. while (!isdigit(c) && c != '-') c = getchar();
  20. if (c == '-') w = , c = getchar();
  21. while (isdigit(c)) {
  22. x = (x<<) + (x<<) + c -'';
  23. c = getchar();
  24. }
  25. if (!w) x = -x;
  26. }
  27. template <typename T>
  28. void Write(T x) {
  29. if (x < ) {
  30. putchar('-');
  31. x = -x;
  32. }
  33. if (x > ) Write(x / );
  34. putchar(x % + '');
  35. }
  36. //----------------------------------------------
  37. deque<ll> p[];
  38. ll n, w, ans = ;
  39. char s[];
  40. bool cmp(ll a, ll b) {
  41. return a > b;
  42. }
  43. int main() {
  44. Read(n);
  45. fu(i, , n) {
  46. scanf("%s", s);
  47. Read(w);
  48. if (s[] == '') {
  49. if (s[] == '') p[].push_back(w);
  50. else p[].push_back(w);
  51. } else {
  52. if (s[] == '') p[].push_back(w);
  53. else p[].push_back(w);
  54. }
  55. }
  56. fu(i, , ) sort(p[i].begin(), p[i].end(), cmp);
  57. ll ans = , num = , cnt0 = , cnt1 = ;
  58. fv(i, p[]) {
  59. ans += p[][i];
  60. num++;
  61. cnt0++, cnt1++;
  62. }
  63. while (p[].size() && p[].size()) {
  64. num += ;
  65. cnt1++, cnt0++;
  66. ans += p[].front() + p[].front();
  67. p[].pop_front();
  68. p[].pop_front();
  69. }
  70. int last = cnt1 * - num;
  71. while (last--) {
  72. if (!p[].size() && !p[].size() && !p[].size()) break;
  73. if (p[].size()) {
  74. bool can = ;
  75. if (p[].size() && p[].front() > p[].front()) can = ;
  76. if (p[].size() && p[].front() > p[].front()) can = ;
  77. if (can) {
  78. ans += p[].front();
  79. p[].pop_front();
  80. continue;
  81. }
  82. }
  83. if (p[].size()) {
  84. bool can = ;
  85. if (p[].size() && p[].front() > p[].front()) can = ;
  86. if (p[].size() && p[].front() > p[].front()) can = ;
  87. if (can) {
  88. ans += p[].front();
  89. p[].pop_front();
  90. continue;
  91. }
  92. }
  93. if (p[].size()) {
  94. bool can = ;
  95. if (p[].size() && p[].front() > p[].front()) can = ;
  96. if (p[].size() && p[].front() > p[].front()) can = ;
  97. if (can) {
  98. ans += p[].front();
  99. p[].pop_front();
  100. continue;
  101. }
  102. }
  103. }
  104. /*if (p[1].size()) {
  105. while (cnt1 * 2 > num && cnt0 * 2 > num) {
  106. if (!p[1].size() && !p[0].size()) break;
  107. if (!p[1].size() || !p[0].size()) {
  108. if (!p[1].size()) {
  109. num++;
  110. ans += p[0].front();
  111. p[0].pop_front();
  112. } else {
  113. num++, cnt0++;
  114. ans += p[1].front();
  115. p[1].pop_front();
  116. }
  117. }
  118. if (p[0].front() > p[1].front()) {
  119. num++;
  120. ans += p[0].front();
  121. p[0].pop_front();
  122. } else {
  123. num++, cnt0++;
  124. ans += p[1].front();
  125. p[1].pop_front();
  126. }
  127. }
  128. } else if (p[2].size()) {
  129. while (cnt1 * 2 > num && cnt0 * 2 > num) {
  130. if (!p[2].size() && !p[0].size()) break;
  131. if (!p[2].size() || !p[0].size()) {
  132. if (!p[2].size()) {
  133. num++;
  134. ans += p[0].front();
  135. p[0].pop_front();
  136. } else {
  137. num++, cnt1++;
  138. ans += p[2].front();
  139. p[2].pop_front();
  140. }
  141. }
  142. if (p[0].front() > p[2].front()) {
  143. num++;
  144. ans += p[0].front();
  145. p[0].pop_front();
  146. } else {
  147. num++, cnt1++;
  148. ans += p[2].front();
  149. p[2].pop_front();
  150. }
  151. }
  152. }
  153. while (p[0].size() && cnt1 * 2 > num && cnt0 * 2 > num) {
  154. num++;
  155. ans += p[0].front();
  156. p[0].pop_front();
  157. }*/
  158. Write(ans);
  159. return ;
  160. }

Problem F

Problem G Monsters and Potions

题目大意

  (请耐心读原题)

  暴力枚举拉力点,暴力枚举一下动的英雄。(能动就直接移动,不是爆搜)

  很好奇为什么只有100多个队过。

Code

  1. //Author: dream_maker
  2. #include<bits/stdc++.h>
  3. using namespace std;
  4. //----------------------------------------------
  5. //typename
  6. typedef long long ll;
  7. //convenient for
  8. #define fu(a, b, c) for (int a = b; a <= c; ++a)
  9. #define fd(a, b, c) for (int a = b; a >= c; --a)
  10. #define fv(a, b) for (int a = 0; a < (signed)b.size(); ++a)
  11. //inf of different typename
  12. const int INF_of_int = 1e9;
  13. const ll INF_of_ll = 1e18;
  14. //fast read and write
  15. template <typename T>
  16. void Read(T &x) {
  17. bool w = ;x = ;
  18. char c = getchar();
  19. while (!isdigit(c) && c != '-') c = getchar();
  20. if (c == '-') w = , c = getchar();
  21. while (isdigit(c)) {
  22. x = (x<<) + (x<<) + c -'';
  23. c = getchar();
  24. }
  25. if (!w) x = -x;
  26. }
  27. template <typename T>
  28. void Write(T x) {
  29. if (x < ) {
  30. putchar('-');
  31. x = -x;
  32. }
  33. if (x > ) Write(x / );
  34. putchar(x % + '');
  35. }
  36. //----------------------------------------------
  37. const int N = ;
  38. ll n, m;
  39. ll s[N], h[N], p[N];
  40. ll now[N], tp[N], tot;
  41. bool wk[N];
  42. void init() {
  43. fu(i, , n) now[i] = p[i];
  44. memset(tp, , sizeof(tp));
  45. memset(wk, , sizeof(wk));
  46. tot = ;
  47. }
  48. bool check_walk(ll fro, ll to, ll vl) {
  49. if (fro == to) return ;
  50. if (fro > to) {
  51. fd(i, fro, to) {
  52. if (now[i] < && vl + now[i] < ) return ;
  53. vl += now[i];
  54. }
  55. return ;
  56. } else {
  57. fu(i, fro, to) {
  58. if (now[i] < && vl + now[i] < ) return ;
  59. vl += now[i];
  60. }
  61. return ;
  62. }
  63. }
  64. void get_clean(ll l, ll r) {
  65. if (l >= r) {
  66. fd(i, l, r) now[i] = ;
  67. } else {
  68. fu(i, l, r) now[i] = ;
  69. }
  70. }
  71. struct Node {
  72. int id, dis;
  73. } w[N];
  74. bool cmp(Node a, Node b) {
  75. return a.dis < b.dis;
  76. }
  77. bool check(int pos) {
  78. init();
  79. fu(i, , m) {
  80. w[i].id = i;
  81. w[i].dis = labs(pos - s[i]);
  82. }
  83. sort(w + , w + m + , cmp);
  84. fu(i, , m) {
  85. if (check_walk(s[w[i].id], pos, h[w[i].id])) {
  86. tp[++tot] = w[i].id;
  87. get_clean(s[w[i].id], pos);
  88. wk[w[i].id] = ;
  89. }
  90. }
  91. fu(i, , m) {
  92. if (!wk[w[i].id]) {
  93. if (!check_walk(s[w[i].id], pos, h[w[i].id])) return ;
  94. tp[++tot] = w[i].id;
  95. wk[w[i].id] = ;
  96. }
  97. }
  98. Write(pos); putchar('\n');
  99. fu(i, , m) {
  100. Write(tp[i]);
  101. putchar(' ');
  102. }
  103. return ;
  104. }
  105. int main() {
  106. Read(n), Read(m);
  107. fu(i, , m) Read(s[i]), Read(h[i]);
  108. fu(i, , n) Read(p[i]);
  109. fu(i, , n)
  110. if (check(i)) return ;
  111. printf("-1");
  112. return ;
  113. }

Problem G

Problem H BerOS File Suggestion

题目大意

  给定$n$个字符串,每次询问一个字符串,问有多少个字符串包含它作为子串,然后要求随便输出$n$个串中任意一个满足条件的串。

  居然有人写AC自动机。牛逼。

  我直接Hash。好像可以直接开一个string映射到xxx的map。

  感觉我对STL一无所知。

Code

  1. /**
  2. * Codeforces
  3. * Problem#1070E
  4. * Accepted
  5. * Time: 234ms
  6. * Memory: 15900k
  7. * Author: yyf
  8. */
  9. #include <iostream>
  10. #include <cstdlib>
  11. #include <cstdio>
  12. #include <map>
  13. using namespace std;
  14. typedef bool boolean;
  15. #define ull unsigned long long
  16.  
  17. ull base = ;
  18.  
  19. const int N = 1e4 + ;
  20.  
  21. int n, q;
  22. char strs[N][];
  23. map<ull, int> cnt;
  24. map<ull, int> lst;
  25.  
  26. inline void init() {
  27. scanf("%d", &n);
  28. for (int i = ; i <= n; i++) {
  29. scanf("%s", strs[i]);
  30. char *s = strs[i];
  31. for (int l = ; s[l]; l++) {
  32. ull ha = ;
  33. for (int r = l; s[r]; r++) {
  34. ha = ha * base + s[r];
  35. if (lst[ha] != i) {
  36. lst[ha] = i;
  37. cnt[ha]++;
  38. // cerr << "added" << " " << ha << endl;
  39. }
  40. }
  41. }
  42. }
  43. }
  44.  
  45. char str[];
  46. inline void solve() {
  47. scanf("%d", &q);
  48. while (q--) {
  49. scanf("%s", str);
  50. ull ha = ;
  51. for (int i = ; str[i]; i++)
  52. ha = ha * base + str[i];
  53. int r1 = cnt[ha];
  54. if (r1)
  55. printf("%d %s\n", r1, strs[lst[ha]]);
  56. else
  57. puts("0 -");
  58. }
  59. }
  60.  
  61. int main() {
  62. init();
  63. solve();
  64. return ;
  65. }

Problem H

Problem I Privatization of Roads in Berland

题目大意

  给定一个$n$个点$m$条边的无向图,有足够多个公司,将每条边分配给一个公司,满足:

  1. 一个公司最多拥有两条边
  2. 每个顶点相邻的边至多被分给$K$个公司。

  容易发现,如果一个公司拥有了两条边,那么它存在一个公共顶点会比较优。

  考虑如果一个顶点的度数大于$K$,那么我们就要硬点它周边$2(d - k)$条边两两配对。

  然后每条边建一个点做匹配就完了。

Code

  1. /**
  2. * Codeforces
  3. * Problem#1070I
  4. * Accepted
  5. * Time: 31ms
  6. * Memory: 200k
  7. */
  8. #include <bits/stdc++.h>
  9. using namespace std;
  10. typedef bool boolean;
  11.  
  12. #define ull unsigned long long
  13. #define pii pair<int, int>
  14. #define ll long long
  15. #define ui unsigned
  16. #define sc second
  17. #define fi first
  18.  
  19. const signed ll llf = (signed ll) (~0ull >> );
  20. const signed int inf = (signed) (~0u >> );
  21.  
  22. template <typename T>
  23. T __abs(T x) {
  24. return (x < ) ? (-x) : (x);
  25. }
  26.  
  27. template <typename T>
  28. void pfill(T* pst, const T* ped, T val) {
  29. for ( ; pst != ped; *(pst++) = val);
  30. }
  31.  
  32. template <typename T>
  33. void pcopy(T* pst, const T* ped, T* pv) {
  34. for ( ; pst != ped; *(pst++) = *(pv++));
  35. }
  36.  
  37. typedef class Edge {
  38. public:
  39. int ed, nx, cap, f;
  40.  
  41. Edge() { }
  42. Edge(int ed, int nx, int cap, int f):ed(ed), nx(nx), cap(cap), f(f) { }
  43. }Edge;
  44.  
  45. typedef class MapManager {
  46. public:
  47. int *h;
  48. vector<Edge> es;
  49.  
  50. MapManager() { }
  51. MapManager(int n) {
  52. h = new int[(n + )];
  53. pfill(h, h + n + , -);
  54. }
  55.  
  56. void addEdge(int u, int v, int cap, int f) {
  57. es.push_back(Edge(v, h[u], cap, f));
  58. h[u] = (signed) es.size() - ;
  59. }
  60.  
  61. void addArc(int u, int v, int cap) {
  62. addEdge(u, v, cap, );
  63. addEdge(v, u, cap, cap);
  64. }
  65.  
  66. Edge& operator [] (int p) {
  67. return es[p];
  68. }
  69.  
  70. void clear() {
  71. delete[] h;
  72. es.clear();
  73. }
  74. }MapManager;
  75.  
  76. const int N = ;
  77.  
  78. int n, m, K;
  79. int s = , t;
  80. int mxcap;
  81. int deg[N];
  82. MapManager g;
  83.  
  84. inline void init() {
  85. scanf("%d%d%d", &n, &m, &K);
  86. pfill(deg, deg + n + , );
  87. g = MapManager(n + m + );
  88. for (int i = , u, v; i <= m; i++) {
  89. scanf("%d%d", &u, &v);
  90. deg[u]++, deg[v]++;
  91. g.addArc(, i, );
  92. g.addArc(i, u + m, );
  93. g.addArc(i, v + m, );
  94. }
  95. t = n + m + , mxcap = ;
  96. for (int i = ; i <= n; i++)
  97. if (deg[i] > K)
  98. g.addArc(i + m, t, (deg[i] - K) << ), mxcap += deg[i] - K;
  99. mxcap <<= ;
  100. }
  101.  
  102. int cur[N << ], _div[N << ];
  103.  
  104. int dfs(int p, int mf) {
  105. if (p == t || !mf)
  106. return mf;
  107. int f, flow = ;
  108. for (int& i = cur[p], e; ~i; i = g[i].nx) {
  109. e = g[i].ed;
  110. if (g[i].f < g[i].cap && _div[e] == _div[p] + && (f = dfs(e, min(mf, g[i].cap - g[i].f))) > ) {
  111. g[i].f += f;
  112. g[i ^ ].f -= f;
  113. mf -= f;
  114. flow += f;
  115. if (!mf)
  116. break;
  117. }
  118. }
  119. return flow;
  120. }
  121.  
  122. queue<int> que;
  123. boolean bfs() {
  124. pfill(_div, _div + t + , -);
  125. _div[s] = ;
  126. que.push(s);
  127. while (!que.empty()) {
  128. int e = que.front();
  129. que.pop();
  130. for (int i = g.h[e], eu; ~i; i = g[i].nx) {
  131. eu = g[i].ed;
  132. if (g[i].cap == g[i].f)
  133. continue;
  134. if (~_div[eu])
  135. continue;
  136. _div[eu] = _div[e] + ;
  137. que.push(eu);
  138. }
  139. }
  140. return _div[t] != -;
  141. }
  142.  
  143. int dinic() {
  144. int rt = ;
  145. while (bfs()) {
  146. pcopy(cur, cur + t + , g.h);
  147. rt += dfs(s, inf);
  148. }
  149. return rt;
  150. }
  151.  
  152. int lab[N];
  153. vector<int> mat[N];
  154.  
  155. inline void solve() {
  156. int flow = dinic(), used = ;
  157.  
  158. if (flow != mxcap) {
  159. for (int i = ; i <= m; i++)
  160. printf("0 ");
  161. putchar('\n');
  162. return;
  163. }
  164.  
  165. for (int i = ; i <= n; i++)
  166. mat[i].clear();
  167.  
  168. for (int i = ; i <= m; i++)
  169. for (int j = g.h[i]; ~j; j = g[j].nx)
  170. if (g[j].cap == g[j].f && g[j].ed > m) {
  171. mat[g[j].ed - m].push_back(i);
  172. break;
  173. }
  174.  
  175. pfill(lab + , lab + m + , );
  176. for (int i = , a, b; i <= n; i++)
  177. while (!mat[i].empty()) {
  178. a = mat[i].back();
  179. mat[i].pop_back();
  180. b = mat[i].back();
  181. mat[i].pop_back();
  182.  
  183. lab[a] = lab[b] = ++used;
  184. }
  185.  
  186. for (int i = ; i <= m; i++) {
  187. if (!lab[i])
  188. lab[i] = ++used;
  189. printf("%d ", lab[i]);
  190. }
  191. putchar('\n');
  192. }
  193.  
  194. inline void clear() {
  195. g.clear();
  196. }
  197.  
  198. int T;
  199. int main() {
  200. scanf("%d", &T);
  201. while (T--) {
  202. init();
  203. solve();
  204. clear();
  205. }
  206. return ;
  207. }

Problem I

Problem J Streets and Avenues in Berhattan

题目大意

  给定一个长度为$K$的字母串,以及$n, m$,要求在$K$中选出不同位置的$n$个字符和$m$个字符,使得$n$个字符中和$m$字符中相同的对数尽量小。

  容易发现算贡献的只有一种字符。

  然后枚举它,随便dp一下就过了。

  时间复杂度$O(n|\Sigma|^2)$

  感觉用多项式除法可以去掉一个平方。

Code

  1. /**
  2. * Codeforces
  3. * Problem#1070J
  4. * Accepted
  5. * Time: 46ms
  6. * Memory: 1200k
  7. * Author: yyf
  8. */
  9. #include <bits/stdc++.h>
  10. using namespace std;
  11. typedef bool boolean;
  12.  
  13. template <typename T>
  14. void pfill(T* pst, const T* ped, T val) {
  15. for ( ; pst != ped; *(pst++) = val);
  16. }
  17.  
  18. const int N = 2e5 + , Alpha = ;
  19.  
  20. int T;
  21. int n, m, K;
  22. int cnt[Alpha];
  23. boolean f[N];
  24. int g[N];
  25. char str[N];
  26.  
  27. inline void init() {
  28. scanf("%d%d%d", &n, &m, &K);
  29. scanf("%s", str);
  30. pfill(cnt, cnt + Alpha, );
  31. for (char *p = str; *p; p++)
  32. cnt[*p - 'A']++;
  33. }
  34.  
  35. inline void solve() {
  36. int res = (signed) (~0u >> );
  37. for (int i = , used, diff; i < Alpha && res; i++) {
  38. pfill(f, f + K + , false);
  39. f[] = true;
  40. for (int c = , s = ; c < Alpha; c++)
  41. if (cnt[c] && (c ^ i)) {
  42. for (int j = s; ~j; j--)
  43. f[j + cnt[c]] |= f[j];
  44. s += cnt[c];
  45. }
  46.  
  47. for (int j = ; j <= K; j++)
  48. g[j] = (f[j] ? j : K + );
  49. for (int j = K - ; ~j; j--)
  50. g[j] = min(g[j + ], g[j]);
  51.  
  52. for (int c = ; c <= cnt[i] && c <= n && res; c++) {
  53. used = g[n - c] + c;
  54. if (K - used >= m) {
  55. diff = K - cnt[i] - g[n - c];
  56. if (diff >= m)
  57. res = ;
  58. else
  59. res = min(res, (m - diff) * c);
  60. }
  61. }
  62. }
  63. printf("%d\n", res);
  64. }
  65.  
  66. int main() {
  67. scanf("%d", &T);
  68. while (T--) {
  69. init();
  70. solve();
  71. }
  72. return ;
  73. }

Problem J

Problem K Video Posts

题目大意

  (没听过)

  (听说是普及题)

Code

  1. //Author: dream_maker
  2. #include<bits/stdc++.h>
  3. using namespace std;
  4. //----------------------------------------------
  5. //typename
  6. typedef long long ll;
  7. //convenient for
  8. #define fu(a, b, c) for (int a = b; a <= c; ++a)
  9. #define fd(a, b, c) for (int a = b; a >= c; --a)
  10. #define fv(a, b) for (int a = 0; a < (signed)b.size(); ++a)
  11. //inf of different typename
  12. const int INF_of_int = 1e9;
  13. const ll INF_of_ll = 1e18;
  14. //fast read and write
  15. template <typename T>
  16. void Read(T &x) {
  17. bool w = ;x = ;
  18. char c = getchar();
  19. while (!isdigit(c) && c != '-') c = getchar();
  20. if (c == '-') w = , c = getchar();
  21. while (isdigit(c)) {
  22. x = (x<<) + (x<<) + c -'';
  23. c = getchar();
  24. }
  25. if (!w) x = -x;
  26. }
  27. template <typename T>
  28. void Write(T x) {
  29. if (x < ) {
  30. putchar('-');
  31. x = -x;
  32. }
  33. if (x > ) Write(x / );
  34. putchar(x % + '');
  35. }
  36. //----------------------------------------------
  37. const int N = 1e5 + ;
  38. ll n, k, a[N], ans[N];
  39. int main() {
  40. Read(n), Read(k);
  41. fu(i, , n) Read(a[i]), a[i] += a[i - ];
  42. if (a[n] % k) {
  43. printf("No");
  44. return ;
  45. }
  46. ll len = a[n] / k, last = , tot = ;
  47. fu(i, , n) {
  48. if (a[i] - a[last] == len) {
  49. ans[++tot] = i - last;
  50. last = i;
  51. } else if(a[i] - a[last] > len) {
  52. printf("No");
  53. return ;
  54. }
  55. }
  56. printf("Yes\n");
  57. fu(i, , k) {
  58. Write(ans[i]);
  59. putchar(' ');
  60. }
  61. return ;
  62. }

Problem K

Problem L Odd Federalization

题目大意

  要求把$n$个点$m$条边分成$r$个部分,使得每一部分每个点的度都是偶数(不看不在同一部分内的边),问最小的$r$和方案。

  首先来猜想答案小于等于2.

  然后把每个点在哪个集合看成未知数$x_i$。

  用异或算一下每个点被割掉的边的奇偶性,然后就可以列方程了。

  高斯消元 + bitset就可以过了。

  证明可以见:http://codeforces.com/blog/entry/62570?#comment-465420 (orz Um_nik)

  没怎么看懂。然后我来口胡两句。

  如果上面的方程存在解,答案一定小于等于2.否则必然存在若干行在模2意义下的向量加得到零向量,并且对应常数项加起来同于1。

  不妨设这些点是$1, 2, \dots, k$,对应的行向量是$\overrightarrow{x_{1}},\overrightarrow{x_2},\dots,\overrightarrow{x_k}$,这些行对应的常数项是$y_1, y_2, \dots, y_k$。

  由列方程的方法可以知道$y_i \equiv deg_i \pmod{2}$

  那么设$\sum_{i = 1}^{k} y_{i}\equiv \sum_{i = 1}^{k} deg_{i} = D \pmod{2}$,因为$\overrightarrow{x_{1}} + \overrightarrow{x_2} + \cdots + \overrightarrow{x_k} = \vec{0}$,所以当某个点的标号$a > k$时,那么$1$到$k$中的点与它相连的边的数量一定是偶数(不然这一维得到的和不是0),假设这一部分总边数是$E$,那么我们愉快地得到了$D\equiv D - E$。

  我们考虑$D - E$有着什么美妙的意义。我们考虑$G' = (V' = \left \{1, 2, \cdots, k\right \}, E')$这个诱导子图。$D - E$把满足$x \in V', y\not \in V'$的边$(x, y)$的贡献除去,因此$D - E$等于这个诱导子图中所有点的度数之和。它不可能是奇数。所以$D \equiv 0\pmod{2}$。

Code

  1. /**
  2. * Codeforces
  3. * Problem#1070L
  4. * Accepted
  5. * Time: 93ms
  6. * Memory: 500k
  7. */
  8. #include <bits/stdc++.h>
  9. using namespace std;
  10. typedef bool boolean;
  11.  
  12. #define ull unsigned long long
  13. #define pii pair<int, int>
  14. #define ll long long
  15. #define ui unsigned
  16. #define sc second
  17. #define fi first
  18.  
  19. const signed ll llf = (signed ll) (~0ull >> );
  20. const signed int inf = (signed) (~0u >> );
  21.  
  22. template <typename T>
  23. T __abs(T x) {
  24. return (x < ) ? (-x) : (x);
  25. }
  26.  
  27. template <typename T>
  28. void pfill(T* pst, const T* ped, T val) {
  29. for ( ; pst != ped; *(pst++) = val);
  30. }
  31.  
  32. template <typename T>
  33. void pcopy(T* pst, const T* ped, T* pv) {
  34. for ( ; pst != ped; *(pst++) = *(pv++));
  35. }
  36.  
  37. const int N = ;
  38.  
  39. int n, m;
  40. boolean deg[N];
  41. bitset<N> eq[N];
  42.  
  43. void reverse(bitset<N> &bs, int bit) {
  44. if (bs.test(bit))
  45. bs.reset(bit);
  46. else
  47. bs.set(bit);
  48. }
  49.  
  50. inline void init() {
  51. scanf("%d%d", &n, &m);
  52. pfill(deg, deg + n, false);
  53. for (int i = ; i < n; i++)
  54. eq[i].reset();
  55. for (int i = , u, v; i <= m; i++) {
  56. scanf("%d%d", &u, &v);
  57. u--, v--;
  58. eq[u].set(v);
  59. eq[v].set(u);
  60. reverse(eq[u], u);
  61. reverse(eq[v], v);
  62. deg[u] = !deg[u], deg[v] = !deg[v];
  63. }
  64. }
  65.  
  66. void guass() {
  67. for (int i = ; i < n; i++) {
  68. int p = -;
  69. for (int j = i; j < n && p == -; j++)
  70. if (eq[j].test(i))
  71. p = j;
  72. if (p == -)
  73. continue;
  74. swap(eq[p], eq[i]);
  75. swap(deg[p], deg[i]);
  76. for (int j = ; j < n; j++)
  77. if ((j ^ i) && eq[j].test(i))
  78. eq[j] ^= eq[i], deg[j] ^= deg[i];
  79. }
  80. }
  81.  
  82. inline void solve() {
  83. guass();
  84. int r = ;
  85. for (int i = ; i < n && r == ; i++)
  86. if (deg[i])
  87. r = ;
  88. printf("%d\n", r);
  89. for (int i = ; i < n; i++)
  90. printf("%d ", deg[i] + );
  91. puts("");
  92. }
  93.  
  94. int T;
  95. int main() {
  96. scanf("%d", &T);
  97. while (T--) {
  98. init();
  99. solve();
  100. }
  101. return ;
  102. }

Problem L

Problem M Algoland and Berland

题目大意

  平面上有$n$个白点和$m$个黑点,满足任意三点不共线,要求给出一个生成树满足:

  • 每条边是平面上的一条线段,边与边只在端点处相交
  • 每条边恰好连接一个白点和一个黑点
  • 第$i$个黑点的度数为$r_i$,保证$r_1 + r_2 + \cdots + r_m = n + m - 1$

  神仙题。orz yjq_naiive & 他的数竞同学。

  设$r = \max\left \{ r_1, r_2, \dots, r_{m}\right \}$

  若$r = 1$,则$n + m = 2$,构造是显然的。

  若$r > 1$,考虑选出$r$最大的点$P$。

  考虑用一条经过$P$的直线将整个平面分成两个部分(先假设是可行的)。对于每部分我们都能够得到若干生成树,然后$P$向它们连边,这样就得到了解。

  如何保证这个能够得到若干个生成树,它的一个必要条件是$|E| - |V| \leqslant -1$。

  如何表示$|E| - |V|$?我们将每个点的赋一个权值$r_i - 1$(如果这个点是白点,那么它的$r_i$记为0),这样一部分内的点权和就是这一部分的$|E| - |V|$。(等价于把$|V|$的贡献摊在每个点上)

  当知道一部分$|E| - |V|$后可以计算出$P$需要向它们连的边数:$x = |V| - |E|$。

  我们知道$1\leqslant x \leqslant r - 1$,所以$1 - r \leqslant |V| - |E| \leqslant -1$

  然后我们把$P$当成两个点分别加入两个部分,这两半部分分别是一个子问题,可以递归处理。

  现在我们来证明一下必定存在这样一条直线满足条件。我们考虑随便找一条经过$P$的直线,记某一半的点权和为$s$,然后顺时针转动这条直线,每遇到一个点$s$至多会改变$r - 1$。如果存在一个不合法的时刻,那么必然满足$s < 1 - r$或者$s > -1$,考虑当直线旋转180度以后,这样$s' = r - s$,因为变化了至少$r$,所以必然存在某个时刻$1 - r \leqslant s \leqslant -1$。

  于是这道题愉快地被通过啦。时间复杂度$O(n^2\log n)$

Code

  1. /**
  2. * Codeforces
  3. * Problem#1070M
  4. * Accepted
  5. * Time: 624ms
  6. * Memory: 106100k
  7. */
  8. #include <algorithm>
  9. #include <iostream>
  10. #include <cassert>
  11. #include <cstdlib>
  12. #include <cstdio>
  13. #include <vector>
  14. #include <cmath>
  15. using namespace std;
  16. typedef bool boolean;
  17.  
  18. template <typename T>
  19. void pfill(T* pst, const T* ped, T val) {
  20. for ( ; pst != ped; *(pst++) = val);
  21. }
  22.  
  23. const double pi = acos(-);
  24. const double eps = ;
  25.  
  26. typedef class Point {
  27. public:
  28. int x, y, deg, id;
  29.  
  30. Point():x(), y(), deg(), id() { }
  31. Point(Point p, int ndeg):x(p.x), y(p.y), deg(ndeg), id(p.id) { }
  32. Point(int x, int y, int deg):x(x), y(y), deg(deg), id() { }
  33. }Point;
  34.  
  35. typedef class Event {
  36. public:
  37. int val, id;
  38. boolean add;
  39. double theta;
  40.  
  41. Event() {}
  42. Event(int val, int id, boolean add, double theta):val(val), id(id), add(add), theta(theta) { }
  43.  
  44. boolean operator < (Event e) const {
  45. return theta < e.theta;
  46. }
  47. }Event;
  48.  
  49. const int N = 6e3 + ;
  50.  
  51. int T;
  52. int n, m;
  53. int rs[N];
  54. int tp = ;
  55. boolean onleft[N];
  56. Event events[N << ];
  57. vector<Point> ps;
  58.  
  59. inline void init() {
  60. scanf("%d%d", &n, &m);
  61. ps.clear();
  62. ps = vector<Point>(n + m);
  63. for (int i = ; i < m; i++)
  64. scanf("%d", rs + i);
  65. for (int i = ; i < n; i++)
  66. scanf("%d%d", &ps[i].x, &ps[i].y), ps[i].deg = , ps[i].id = i + ;
  67. for (int i = ; i < m; i++)
  68. scanf("%d%d", &ps[i + n].x, &ps[i + n].y), ps[i + n].deg = rs[i], ps[i + n].id = i + ;
  69. }
  70.  
  71. void solve(vector<Point> &ps) {
  72. int r = , mxid = -;
  73. for (int i = ; i < (signed) ps.size(); i++)
  74. if (ps[i].deg > r)
  75. r = ps[i].deg, mxid = i;
  76. if (r == ) {
  77. int cnt = ;
  78. for (int i = ; i < (signed) ps.size(); i++)
  79. if (!ps[i].deg)
  80. mxid = i, cnt++;
  81. assert(cnt == || ps.size() == );
  82. for (int i = ; i < (signed) ps.size(); i++)
  83. if (i ^ mxid)
  84. printf("%d %d\n", ps[i].id, ps[mxid].id);
  85. return;
  86. }
  87.  
  88. int dx, dy;
  89. double theta;
  90. tp = ;
  91. int sum = ;
  92. for (int i = ; i < (signed) ps.size(); i++) {
  93. if (i == mxid)
  94. continue;
  95. dx = ps[i].x - ps[mxid].x, dy = ps[i].y - ps[mxid].y;
  96. theta = atan2(dy, dx);
  97. if (theta > || fabs(theta) < eps) {
  98. sum += ps[i].deg - , onleft[i] = true;
  99. events[tp++] = Event( - ps[i].deg, i, false, theta);
  100. } else
  101. events[tp++] = Event(ps[i].deg - , i, true, theta + pi);
  102. }
  103.  
  104. sort(events, events + tp);
  105. for (int i = ; i < tp && (sum < - r || sum > -); i++) {
  106. sum += events[i].val;
  107. onleft[events[i].id] = events[i].add;
  108. }
  109.  
  110. assert(sum >= - r && sum <= -);
  111.  
  112. vector<Point> pl, pr;
  113. for (int i = ; i < (signed) ps.size(); i++) {
  114. if (i == mxid)
  115. continue;
  116. if (onleft[i])
  117. pl.push_back(ps[i]);
  118. else
  119. pr.push_back(ps[i]);
  120. }
  121. pfill(onleft, onleft + ps.size(), false);
  122. pl.push_back(Point(ps[mxid], -sum));
  123. pr.push_back(Point(ps[mxid], r + sum));
  124. ps.clear();
  125.  
  126. solve(pl);
  127. solve(pr);
  128. }
  129.  
  130. inline void solve() {
  131. puts("YES");
  132. solve(ps);
  133. }
  134.  
  135. int main() {
  136. scanf("%d", &T);
  137. while (T--) {
  138. init();
  139. solve();
  140. }
  141. return ;
  142. }

Problem M

2018-2019 ICPC, NEERC, Southern Subregional Contest (Online Mirror) Solution的更多相关文章

  1. 2018.10.20 2018-2019 ICPC,NEERC,Southern Subregional Contest(Online Mirror, ACM-ICPC Rules)

    i207M的“怕不是一个小时就要弃疗的flag”并没有生效,这次居然写到了最后,好评=.= 然而可能是退役前和i207M的最后一场比赛了TAT 不过打得真的好爽啊QAQ 最终结果: 看见那几个罚时没, ...

  2. 2018-2019 ICPC, NEERC, Southern Subregional Contest (Online Mirror, ACM-ICPC Rules, Teams Preferred)

    A. Find a Number 找到一个树,可以被d整除,且数字和为s 记忆化搜索 static class S{ int mod,s; String str; public S(int mod, ...

  3. 2018-2019 ICPC, NEERC, Southern Subregional Contest (Online Mirror, ACM-ICPC Rules, Teams Preferred) Solution

    A. Find a Number Solved By 2017212212083 题意:$找一个最小的n使得n % d == 0 并且 n 的每一位数字加起来之和为s$ 思路: 定义一个二元组$< ...

  4. Codeforces1070 2018-2019 ICPC, NEERC, Southern Subregional Contest (Online Mirror, ACM-ICPC Rules, Teams Preferred)总结

    第一次打ACM比赛,和yyf两个人一起搞事情 感觉被两个学长队暴打的好惨啊 然后我一直做傻子题,yyf一直在切神仙题 然后放一波题解(部分) A. Find a Number LINK 题目大意 给你 ...

  5. codeforce1070 2018-2019 ICPC, NEERC, Southern Subregional Contest (Online Mirror, ACM-ICPC Rules, Teams Preferred) 题解

    秉承ACM团队合作的思想懒,这篇blog只有部分题解,剩余的请前往星感大神Star_Feel的blog食用(表示男神汉克斯更懒不屑于写我们分别代写了下...) C. Cloud Computing 扫 ...

  6. 2018-2019 ICPC, NEERC, Southern Subregional Contest

    目录 2018-2019 ICPC, NEERC, Southern Subregional Contest (Codeforces 1070) A.Find a Number(BFS) C.Clou ...

  7. Codeforces 2018-2019 ICPC, NEERC, Southern Subregional Contest

    2018-2019 ICPC, NEERC, Southern Subregional Contest 闲谈: 被操哥和男神带飞的一场ACM,第一把做了这么多题,荣幸成为7题队,虽然比赛的时候频频出锅 ...

  8. 2016-2017 ACM-ICPC, NEERC, Southern Subregional Contest (Online Mirror) in codeforces(codeforces730)

    A.Toda 2 思路:可以有二分来得到最后的数值,然后每次排序去掉最大的两个,或者3个(奇数时). /************************************************ ...

  9. 【*2000】【2018-2019 ICPC, NEERC, Southern Subregional Contest C 】Cloud Computing

    [链接] 我是链接,点我呀:) [题意] [题解] 我们可以很容易知道区间的每个位置有哪些安排可以用. 显然 我们优先用那些花费的钱比较少的租用cpu方案. 但一个方案可供租用的cpu有限. 我们可以 ...

随机推荐

  1. E - Heavy Transportation

    来源poj1797 Background Hugo Heavy is happy. After the breakdown of the Cargolifter project he can now ...

  2. react 使用 react-loadable分包

    文档 yarn add react-loadable 使用 import Loadable from "@/components/loadable"; const Home = L ...

  3. memoization提升递归效率

    从开通博客到目前为止,也有一年了,刚开始的写了一篇工作的感想,然后就一直不知道写什么,看园子里的文章实在是很专业,怕自己写的太水.但是,写一些东西总归是好的,于是就当作是记笔记一样,开始写第一篇技术类 ...

  4. 使用 ASP.NET SignalR实现实时通讯

    ASP.NET SignalR 是为 ASP.NET 开发人员提供的一个库,可以简化开发人员将实时 Web 功能添加到应用程序的过程.实时 Web 功能是指这样一种功能:当所连接的客户端变得可用时服务 ...

  5. mui 窗口管理及窗口之间的数据传递

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name ...

  6. 怎么在Centos7 下让我的mariadb开机启动?(已解决)

    以前我经常使用syscemctl工具在开机后执行 systemctl start mariadb (哈哈,打得可6,只是有点儿麻烦), 如果能开机自启动mariadb就好了. 所以,我想百度下看什么命 ...

  7. AJAX方法讲解

    Ajax的方法讲解 Ajax 异步请求,有点: 调高用户的体验度, 降低网络传输量 $.load() //异步加载页面 $.post()  Post 异步请求 $.post("url请求地址 ...

  8. 终于等到你!WebOptimizer - A bundler and minifier for ASP.NET Core

    迷人的 ASP.NET Core 有一个美中不足之处,自从一开始接触它到现在,我就一直不喜欢,一直想找到替代品,甚至想过自己实现一个,它就是 BundlerMinifier . 昨天面对 bundle ...

  9. winform中按钮透明的方法

    把Button设为透明的方法:1.修改 FlatAppearance属性下的BorderSize 为0  修改 FlatStyle 的属性为 Flat 2. /// <summary>// ...

  10. day17:递归函数

    1,递归函数是一个函数体系,非常的难 2,练习题一 # 3.用map来处理字符串列表,把列表中所有人都变成sb,比方alex_sb name=['alex','wupeiqi','yuanhao',' ...