2018-2019 ICPC, NEERC, Southern Subregional Contest (Online Mirror) Partial Solution

Posted yyf0309

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2018-2019 ICPC, NEERC, Southern Subregional Contest (Online Mirror) Partial Solution相关的知识,希望对你有一定的参考价值。

瞎扯

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

技术分享图片

  果然我是标准的普及组选手。(这个队名是啥意思?我也不知道,因为不知道取啥队名,就随机在键盘上敲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 = 5005, D = 505;
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 * 10 + 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(0, 0));
39     memset(f, 0x3f, sizeof(f));
40     f[0][0] = 0, vis[0][0] = true;
41     while (!que.empty()) {
42         pii e = que.front();
43         que.pop();
44 
45         for (int i = 0; i <= 9; 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 + 0;
53             lstr[eu.fi][eu.sc] = e.sc;
54             f[eu.fi][eu.sc] = f[e.fi][e.sc] + 1;
55             que.push(eu);
56         }
57     }
58     return vis[s][0];
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] + 0, nr);
66     putchar(lst[s][r]);
67 }
68 
69 
70 inline void solve() {
71     if (bfs()) {
72         print(s, 0);
73     } else
74         puts("-1");
75 }
76 
77 int main() {
78     init();
79     solve();
80     return 0;
81 }
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 >> 1);
 20 const signed int inf = (signed) (~0u >> 1);
 21 
 22 template <typename T>
 23 T __abs(T x) {
 24     return (x < 0) ? (-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 - 0; ++s, digit(*s); u = u * 10 + *s - 0);
 45     return s;
 46 }
 47 
 48 const int N = 2e5 + 5;
 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[100];
 71 
 72 Segment read() {
 73     ui l, r, x;
 74     scanf("%s", buf);
 75     ui sgn = (buf[0] == +);
 76     char* str = buf + 1;
 77     str = read(str, l);
 78     str = read(str, x), l = l << 8 | x;
 79     str = read(str, x), l = l << 8 | x;
 80     str = read(str, x), l = l << 8 | x;
 81     if (*str == /) {
 82         read(str, x);
 83         x = 32 - x;
 84         l >>= x, l <<= x;
 85         if (x == 32)
 86             r = ~0u;
 87         else
 88             r = l | ((1 << x) - 1);
 89         return Segment(l, r, sgn);
 90     }
 91     return Segment(l, l, sgn);
 92 }
 93 
 94 int res = 0;
 95 vector<Segment> ss, rs;
 96 
 97 inline void init() {
 98     scanf("%d", &n);
 99     Segment s;
100     for (int i = 1; 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 = 0; i < ss.size(); i++)
109         app1 |= (ss[i].sgn == 1), app0 |= (ss[i].sgn == 0);
110     
111     if (!app1) {
112         rs.push_back(Segment(l, 32 - bit, 0));
113         return;
114     }
115 
116     if (!app0)
117         return;
118 
119     assert(l ^ r);
120 
121     ui mid = l + ((r - l) >> 1);
122     vector<Segment> ql, qr;
123     for (ui i = 0; 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 + 1, ss[i].r, ss[i].sgn));
131         }
132     }
133     ss.clear();
134     dividing(ql, l, mid, bit - 1);
135     dividing(qr, mid + 1, r, bit - 1);
136 }
137 
138 inline void solve() {
139     sort(ss.begin(), ss.end());
140     for (ui i = 0, j; i < ss.size(); i = j)
141         for (j = i + 1; 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, 0, ~0u, 32);
147     printf("%u
", rs.size());
148     ui msk = (1 << 8) - 1;
149     for (ui i = 0, x; i < rs.size(); i++) {
150         x = rs[i].l;
151         printf("%u.%u.%u.%u/%u
", x >> 24, x >> 16 & msk, x >> 8 & msk, x & msk, rs[i].r);
152     }
153 }
154 
155 int main() {
156     init();
157     solve();
158     return 0;
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 = 21;
 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 + 1)];
 41             memset(ar, 0, sizeof(T) * (s + 1));
 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 = 0;
 51             for ( ; idx; idx -= (idx & (-idx)))
 52                 rt += ar[idx];
 53             return rt;
 54         }
 55 
 56         int kth(int k) {
 57             int rt = 0, cur = 0;
 58             for (int l = (1 << (bzmax - 1)); l; l >>= 1)
 59                 if ((rt | l) <= s && (cur + ar[rt | l]) < k)
 60                     rt |= l, cur += ar[rt];
 61             return rt + 1;
 62         }
 63 };
 64 
 65 #define ll long long
 66 
 67 const int V = 1e6 + 3;
 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 = 1, 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, 1));
 81         vs.push_back(Opt(r + 1, p, c, -1));
 82     }
 83 }
 84 
 85 ll res = 0;
 86 inline void solve() {
 87     sort(vs.begin(), vs.end());
 88     int pv = 0, s = (signed) vs.size();
 89     for (int i = 1; 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 0;
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 = 1;x = 0;
18   char c = getchar();
19   while (!isdigit(c) && c != -) c = getchar();
20   if (c == -) w = 0, c = getchar();
21   while (isdigit(c)) {
22     x = (x<<1) + (x<<3) + c -0;
23     c = getchar();
24   }
25   if (!w) x = -x;
26 }
27 template <typename T>
28 void Write(T x) {
29   if (x < 0) {
30     putchar(-);
31     x = -x; 
32   }
33   if (x > 9) Write(x / 10);
34   putchar(x % 10 + 0);
35 }
36 //----------------------------------------------
37 const int N = 3e5 + 10;
38 ll a[N], n, k, ans = 0;
39 int main() {
40   Read(n), Read(k);
41   fu(i, 1, n) Read(a[i]);
42   fu(i, 1, n - 1) {
43     if (!a[i]) continue;
44     ll num = a[i] / k;
45     if (a[i] % k) ++num;
46     a[i + 1] = max(0ll, a[i + 1] - (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 0;
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(nlog^{2} n)$。

  但是这个可以二分答案。

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

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

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

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

  然后注意几个地方:

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

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 + 1)];
 31             memset(ar, 0, sizeof(T) * (s + 1));
 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 = 0;
 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 0;
 49             int rt = 0, cur = 0;
 50             for (int i = (1 << 18); i; i >>= 1)
 51                 if ((rt | i) <= s && ar[rt | i] + cur < k)
 52                     rt |= i, cur += ar[rt];
 53             return rt + 1;
 54         }
 55 
 56         void clear() {
 57             s = 0;
 58             delete[] ar;
 59         }
 60 };
 61 
 62 const int N = 2e5 + 5;
 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 = 1; i <= n; i++)
 80         scanf("%d", ps + i), ar[i] = pii(ps[i], i);
 81 }
 82 
 83 int query(int i) {
 84     int l = 1, r = i, mid, k, ti;
 85     ll s = 0;
 86     while (l <= r) {
 87         mid = (l + r) >> 1;
 88         k = itc.kth(mid);
 89         s = its.query(k);
 90         ti = (mid - 1) / m * m;
 91         k = itc.kth(ti);
 92         s += its.query(k);
 93         if (s > t)
 94             r = mid - 1;
 95         else
 96             l = mid + 1;
 97     }
 98     return l - 1;
 99 }
100 
101 inline void solve() {
102     int ansc = 0, ansd = 1;
103     sort(ar + 1, ar + n + 1);
104     int i = 1, 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, 1);
109             its.add(ar[i].sc, ar[i].fi);
110             i++;
111         }
112         c = query(i - 1);
113         if (c > ansc)
114             ansc = c, ansd = ar[i - 1].fi;
115     }
116     printf("%d %d
", 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 0;
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 = 1;x = 0;
 18   char c = getchar();
 19   while (!isdigit(c) && c != -) c = getchar();
 20   if (c == -) w = 0, c = getchar();
 21   while (isdigit(c)) {
 22     x = (x<<1) + (x<<3) + c -0;
 23     c = getchar();
 24   }
 25   if (!w) x = -x;
 26 }
 27 template <typename T>
 28 void Write(T x) {
 29   if (x < 0) {
 30     putchar(-);
 31     x = -x; 
 32   }
 33   if (x > 9) Write(x / 10);
 34   putchar(x % 10 + 0);
 35 }
 36 //----------------------------------------------
 37 deque<ll> p[4];
 38 ll n, w, ans = 0;
 39 char s[3];
 40 bool cmp(ll a, ll b) {
 41   return a > b;
 42 }
 43 int main() {
 44   Read(n);
 45   fu(i, 1, n) {
 46     scanf("%s", s);
 47     Read(w);
 48     if (s[0] == 0) {
 49       if (s[1] == 0) p[0].push_back(w);
 50       else p[1].push_back(w);
 51     } else {
 52       if (s[1] == 0) p[2].push_back(w);
 53       else p[3].push_back(w);
 54     }
 55   }
 56   fu(i, 0, 3) sort(p[i].begin(), p[i].end(), cmp);
 57   ll ans = 0, num = 0, cnt0 = 0, cnt1 = 0;
 58   fv(i, p[3]) {
 59     ans += p[3][i];
 60     num++;
 61     cnt0++, cnt1++;
 62   }
 63   while (p[1].size() && p[2].size()) {
 64     num += 2;
 65     cnt1++, cnt0++;
 66     ans += p[1].front() + p[2].front();
 67     p[1].pop_front();
 68     p[2].pop_front();
 69   }
 70   int last = cnt1 * 2 - num;
 71   while (last--) {
 72     if (!p[0].size() && !p[1].size() && !p[2].size()) break;
 73     if (p[0].size()) {
 74       bool can = 1;
 75       if (p[1].size() && p[1].front() > p[0].front()) can = 0;
 76       if (p[2].size() && p[2].front() > p[0].front()) can = 0;
 77       if (can) {
 78         ans += p[0].front();
 79         p[0].pop_front();
 80         continue;
 81       }
 82     }
 83     if (p[1].size()) {
 84       bool can = 1;
 85       if (p[0].size() && p[0].front() > p[1].front()) can = 0;
 86       if (p[2].size() && p[2].front() > p[1].front()) can = 0;
 87       if (can) {
 88         ans += p[1].front();
 89         p[1].pop_front();
 90         continue;
 91       }
 92     }
 93     if (p[2].size()) {
 94       bool can = 1;
 95       if (p[1].size() && p[1].front() > p[2].front()) can = 0;
 96       if (p[0].size() && p[0].front() > p[2].front()) can = 0;
 97       if (can) {
 98         ans += p[2].front();
 99         p[2].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 0;
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 = 1;x = 0;
 18   char c = getchar();
 19   while (!isdigit(c) && c != -) c = getchar();
 20   if (c == -) w = 0, c = getchar();
 21   while (isdigit(c)) {
 22     x = (x<<1) + (x<<3) + c -0;
 23     c = getchar();
 24   }
 25   if (!w) x = -x;
 26 }
 27 template <typename T>
 28 void Write(T x) {
 29   if (x < 0) {
 30     putchar(-);
 31     x = -x; 
 32   }
 33   if (x > 9) Write(x / 10);
 34   putchar(x % 10 + 0);
 35 }
 36 //----------------------------------------------
 37 const int N = 1010;
 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, 1, n) now[i] = p[i];
 44   memset(tp, 0, sizeof(tp));
 45   memset(wk, 0, sizeof(wk));
 46   tot = 0;
 47 }
 48 bool check_walk(ll fro, ll to, ll vl) {
 49   if (fro == to) return 1;
 50   if (fro > to) {
 51     fd(i, fro, to) {
 52       if (now[i] < 0 && vl + now[i] < 0) return 0;
 53       vl += now[i];
 54     }
 55     return 1;
 56   } else {
 57     fu(i, fro, to) {
 58       if (now[i] < 0 && vl + now[i] < 0) return 0;
 59       vl += now[i];
 60     }
 61     return 1;
 62   }
 63 }
 64 void get_clean(ll l, ll r) {
 65   if (l >= r) {
 66     fd(i, l, r) now[i] = 0;
 67   } else {
 68     fu(i, l, r) now[i] = 0;
 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, 1, m) {
 80     w[i].id = i;
 81     w[i].dis = labs(pos - s[i]);
 82   }
 83   sort(w + 1, w + m + 1, cmp);
 84   fu(i, 1, 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] = 1;
 89     }
 90   }
 91   fu(i, 1, m) {
 92     if (!wk[w[i].id]) { 
 93       if (!check_walk(s[w[i].id], pos, h[w[i].id])) return 0;
 94       tp[++tot] = w[i].id;
 95       wk[w[i].id] = 1;
 96     }
 97   }
 98   Write(pos); putchar(
);
 99   fu(i, 1, m) {
100     Write(tp[i]);
101     putchar( );
102   }
103   return 1;
104 }
105 int main() {
106   Read(n), Read(m);
107   fu(i, 1, m) Read(s[i]), Read(h[i]);
108   fu(i, 1, n) Read(p[i]);
109   fu(i, 1, n)
110     if (check(i)) return 0;
111   printf("-1");
112   return 0;
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 = 233;
18 
19 const int N = 1e4 + 3;
20 
21 int n, q;
22 char strs[N][10];
23 map<ull, int> cnt;
24 map<ull, int> lst;
25 
26 inline void init() {
27     scanf("%d", &n);
28     for (int i = 1; i <= n; i++) {
29         scanf("%s", strs[i]);
30         char *s = strs[i];
31         for (int l = 0; s[l]; l++) {
32             ull ha = 0;
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[10];
46 inline void solve() {
47     scanf("%d", &q);
48     while (q--) {
49         scanf("%s", str);
50         ull ha = 0;
51         for (int i = 0; str[i]; i++)
52             ha = ha * base + str[i];
53         int r1 = cnt[ha];
54         if (r1)
55             printf("%d %s
", r1, strs[lst[ha]]);
56         else
57             puts("0 -");
58     }
59 }
60 
61 int main() {
62     init();
63     solve();
64     return 0;
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 >> 1);
 20 const signed int inf = (signed) (~0u >> 1);
 21 
 22 template <typename T>
 23 T __abs(T x) {
 24     return (x < 0) ? (-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 + 1)];
 53              pfill(h, h + n + 1, -1);
 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() - 1;
 59         }
 60 
 61         void addArc(int u, int v, int cap) {
 62             addEdge(u, v, cap, 0);
 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 = 605;
 77 
 78 int n, m, K;
 79 int s = 0, 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 + 1, 0);
 87     g = MapManager(n + m + 1);
 88     for (int i = 1, u, v; i <= m; i++) {
 89         scanf("%d%d", &u, &v);
 90         deg[u]++, deg[v]++;
 91         g.addArc(0, i, 1);
 92         g.addArc(i, u + m, 1);
 93         g.addArc(i, v + m, 1);
 94     }
 95     t = n + m + 1, mxcap = 0;
 96     for (int i = 1; i <= n; i++)
 97         if (deg[i] > K)
 98             g.addArc(i + m, t, (deg[i] - K) << 1), mxcap += deg[i] - K;
 99     mxcap <<= 1;
100 }
101 
102 int cur[N << 1], _div[N << 1];
103 
104 int dfs(int p, int mf) {
105     if (p == t || !mf)
106         return mf;
107     int f, flow = 0;
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] + 1 && (f = dfs(e, min(mf, g[i].cap - g[i].f))) > 0) {
111             g[i].f += f;
112             g[i ^ 1].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 + 1, -1);
125     _div[s] = 0;
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] + 1;
137             que.push(eu);
138         }
139     }
140     return _div[t] != -1;
141 }
142 
143 int dinic() {
144     int rt = 0;
145     while (bfs()) {
146         pcopy(cur, cur + t + 1, 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 = 0;
157     
158     if (flow != mxcap) {
159         for (int i = 1; i <= m; i++)
160             printf("0 ");
161         putchar(
);
162         return;
163     }
164 
165     for (int i = 1; i <= n; i++)
166         mat[i].clear();
167 
168     for (int i = 1; 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 + 1, lab + m + 1, 0);
176     for (int i = 1, 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 = 1; i <= m; i++) {
187         if (!lab[i])
188             lab[i] = ++used;
189         printf("%d ", lab[i]);
190     }
191     putchar(
);
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 0;
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 + 5, Alpha = 27;
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, 0);
31     for (char *p = str; *p; p++)
32         cnt[*p - A]++;
33 }
34 
35 inline void solve() {
36     int res = (signed) (~0u >> 1);
37     for (int i = 0, used, diff; i < Alpha && res; i++) {
38         pfill(f, f + K + 1, false);
39         f[0] = true;
40         for (int c = 0, s = 0; 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 = 0; j <= K; j++)
48             g[j] = (f[j] ? j : K + 1);
49         for (int j = K - 1; ~j; j--)
50             g[j] = min(g[j + 1], g[j]);
51 
52         for (int c = 0; 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 = 0;
58                 else
59                     res = min(res, (m - diff) * c);
60             }
61         }
62     }
63     printf("%d
", res);
64 }
65 
66 int main() {
67     scanf("%d", &T);
68     while (T--) {
69         init();
70         solve();
71     }
72     return 0;
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 = 1;x = 0;
18   char c = getchar();
19   while (!isdigit(c) && c != -) c = getchar();
20   if (c == -) w = 0, c = getchar();
21   while (isdigit(c)) {
22     x = (x<<1) + (x<<3) + c -0;
23     c = getchar();
24   }
25   if (!w) x = -x;
26 }
27 template <typename T>
28 void Write(T x) {
29   if (x < 0) {
30     putchar(-);
31     x = -x; 
32   }
33   if (x > 9) Write(x / 10);
34   putchar(x % 10 + 0);
35 }
36 //----------------------------------------------
37 const int N = 1e5 + 10;
38 ll n, k, a[N], ans[N];
39 int main() {
40   Read(n), Read(k);
41   fu(i, 1, n) Read(a[i]), a[i] += a[i - 1];
42   if (a[n] % k) {
43     printf("No");
44     return 0;
45   }
46   ll len = a[n] / k, last = 0, tot = 0;
47   fu(i, 1, 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 0;
54     }
55   }
56   printf("Yes
");
57   fu(i, 1, k) {
58     Write(ans[i]);
59     putchar( );
60   }
61   return 0;
62 }
Problem K

Problem L Odd Federalization

题目大意

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

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

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

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

  高斯消元 + bitset就没了。

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 >> 1);
 20 const signed int inf = (signed) (~0u >> 1);
 21 
 22 template <typename T>
 23 T __abs(T x) {
 24     return (x < 0) ? (-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 = 2048;
 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 = 0; i < n; i++)
 54         eq[i].reset();
 55     for (int i = 1, 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 = 0; i < n; i++) {
 68         int p = -1;
 69         for (int j = i; j < n && p == -1; j++)
 70             if (eq[j].test(i))
 71                 p = j;
 72         if (p == -1)
 73             continue;
 74         swap(eq[p], eq[i]);
 75         swap(deg[p], deg[i]);
 76         for (int j = 0; 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 = 1;
 85     for (int i = 0; i < n && r == 1; i++)
 86         if (deg[i])
 87             r = 2;
 88     printf("%d
", r);
 89     for (int i = 0; i < n; i++)
 90         printf("%d ", deg[i] + 1);
 91     puts("");
 92 }
 93 
 94 int T;
 95 int main() {
 96     scanf("%d", &T);
 97     while (T--) {
 98         init();
 99         solve();
100     }
101     return 0;
102 }
Problem L

 

以上是关于2018-2019 ICPC, NEERC, Southern Subregional Contest (Online Mirror) Partial Solution的主要内容,如果未能解决你的问题,请参考以下文章

2018-2019 ICPC, NEERC, Southern Subregional Contest (Online Mirror) 体验记

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

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

Codeforces 1089K - King Kog's Reception - [线段树][2018-2019 ICPC, NEERC, Northern Eurasia Finals P

2013-2014 ACM-ICPC, NEERC, Eastern Subregional Contest PART (7/10)

[算法竞赛入门经典]Kickdown ACM/ICPC NEERC 2004,UVa1587