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$
思路:
定义一个二元组$<d, s>$ 表示当前状态模d的值,以及每一位加起来的值
跑最短路,从$<0, 0> 跑到 <0, s>$
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 const int maxn = 1e5 + 10; 6 const int INF = 0x3f3f3f3f; 7 #define N 510 8 #define M 5010 9 10 int d, s, cnt; 11 char ans[maxn]; 12 int dis[N][M]; 13 int inq[N][M]; 14 int vis[N][M]; 15 16 struct node{ 17 int remind; 18 int sum; 19 node(){} 20 node(int remind, int sum) :remind(remind), sum(sum){} 21 }; 22 23 void Init() 24 { 25 cnt = -1; 26 memset(inq, 0, sizeof inq); 27 memset(dis, 0x3f, sizeof dis); 28 memset(vis, 0, sizeof vis); 29 } 30 31 void BFS() 32 { 33 queue<node>q; 34 dis[0][0] = 0; 35 q.push(node(0, 0)); 36 inq[0][0] = 1; 37 while(!q.empty()) 38 { 39 node st = q.front(); 40 q.pop(); 41 inq[st.remind][st.sum] = 0; 42 for(int i = 0; i < 10; ++i) 43 { 44 node now = node((st.remind * 10 + i) % d, st.sum + i); 45 if(now.sum > s) break; 46 if(dis[now.remind][now.sum] > dis[st.remind][st.sum] + 1) 47 { 48 dis[now.remind][now.sum] = dis[st.remind][st.sum] + 1; 49 if(!inq[now.remind][now.sum]) 50 { 51 inq[now.remind][now.sum] = 1; 52 q.push(now); 53 } 54 } 55 } 56 } 57 } 58 59 int DFS(int D,int S) 60 { 61 if(D == 0 && S == s) return 1; 62 for(int i = 0; i < 10; ++i) 63 { 64 int td = (D * 10 + i) % d; 65 int ts = S + i; 66 if(ts > s) break; 67 if(vis[td][ts]) continue; 68 if(dis[D][S] + 1 != dis[td][ts]) continue; 69 ans[++cnt] = i; 70 if(DFS(td, ts)) return 1; 71 --cnt; 72 } 73 vis[D][S] = 1; 74 return 0; 75 } 76 77 int main() 78 { 79 while(~scanf("%d %d", &d, &s)) 80 { 81 Init(); 82 BFS(); 83 if(dis[0][s] == INF) 84 { 85 puts("-1"); 86 continue; 87 } 88 DFS(0, 0); 89 for(int i = 0; i <= cnt; ++i) printf("%d", ans[i]); 90 puts(""); 91 } 92 return 0; 93 }
B. Berkomnadzor
Unsolved.
C. Cloud Computing
Solved By Dup4
题意:
有一个人需要租用服务器,一共需要n天,每天要k个,供应商会提供一些供应方案,用四元组$<l, r, c, p>$ 表示方案。
$l r 表示 供应的区间, c 表示l, r 区间内每天最多供应c个,p 表示每个服务器的价格$
思路:
考虑用线段树维护 两个值 Min 和 cnt 分别表示区间内最少的服务器需要个数以及区间内还需要购买服务器的天数
对于供应方案,按价格排序之后,从小到大枚举,对于每个方案的$l, r$
如果这个区间内所有还需要购买服务器的天中的 需要购买服务器的数量的最小值都 $> c$ 那么直接区间减即可。
否则 先丢出不符合的,改为INF 再丢进去,标记为不再需要购买服务器,并加上贡献,每个点最多丢出一次。
时间复杂度 $O(mlog^n + nlog^n)$
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define ll long long 5 #define INF 0x3f3f3f3f 6 #define N 1000010 7 int n, k, m; 8 struct qnode 9 { 10 int l, r, c, p; 11 qnode () {} 12 qnode (int l, int r, int c, int p) : l(l), r(r), c(c), p(p) {} 13 void scan() { scanf("%d%d%d%d", &l, &r, &c, &p); } 14 bool operator < (const qnode &r) const { return p < r.p; } 15 }que[N]; 16 17 struct SEG 18 { 19 int lazy[N << 2], Min[N << 2], pos[N << 2], cnt[N << 2]; 20 struct node 21 { 22 int lazy, Min, pos, cnt; 23 node () {} 24 node (int lazy, int Min, int pos, int cnt) : lazy(lazy), Min(Min), pos(pos), cnt(cnt) {} 25 void init() { lazy = 0; Min = INF; pos = 0; cnt = 0; } 26 node operator + (const node &r) const 27 { 28 node res = node(0, INF, 0, 0); 29 res.cnt = cnt + r.cnt; 30 if (Min < r.Min) 31 { 32 res.Min = Min; 33 res.pos = pos; 34 } 35 else 36 { 37 res.Min = r.Min; 38 res.pos = r.pos; 39 } 40 return res; 41 } 42 }a[N << 2], res; 43 void build(int id, int l, int r) 44 { 45 a[id] = node(0, INF, 0, 0); 46 if (l == r) 47 { 48 a[id] = node(0, k, l, 1); 49 return; 50 } 51 int mid = (l + r) >> 1; 52 build(id << 1, l, mid); 53 build(id << 1 | 1, mid + 1, r); 54 a[id] = a[id << 1] + a[id << 1 | 1]; 55 } 56 void change(int id, int lazy) 57 { 58 a[id].lazy += lazy; 59 a[id].Min += lazy; 60 } 61 void pushdown(int id) 62 { 63 if (!a[id].lazy) return; 64 change(id << 1, a[id].lazy); 65 change(id << 1 | 1, a[id].lazy); 66 a[id].lazy = 0; 67 } 68 void update(int id, int l, int r, int ql, int qr, int val) 69 { 70 if (l >= ql && r <= qr) 71 { 72 a[id].Min += val; 73 a[id].lazy += val; 74 return; 75 } 76 pushdown(id); 77 int mid = (l + r) >> 1; 78 if (ql <= mid) update(id << 1, l, mid, ql, qr, val); 79 if (qr > mid) update(id << 1 | 1, mid + 1, r, ql, qr, val); 80 a[id] = a[id << 1] + a[id << 1 | 1]; 81 } 82 void update(int id, int l, int r, int pos) 83 { 84 if (l == r) 85 { 86 a[id].Min = INF; 87 a[id].cnt = 0; 88 return; 89 } 90 pushdown(id); 91 int mid = (l + r) >> 1; 92 if (pos <= mid) update(id << 1, l, mid, pos); 93 else update(id << 1 | 1, mid + 1, r, pos); 94 a[id] = a[id << 1] + a[id << 1 | 1]; 95 } 96 void query(int id, int l, int r, int ql, int qr) 97 { 98 if (l >= ql && r <= qr) 99 { 100 res = res + a[id]; 101 return; 102 } 103 pushdown(id); 104 int mid = (l + r) >> 1; 105 if (ql <= mid) query(id << 1, l, mid, ql, qr); 106 if (qr > mid) query(id << 1 | 1, mid + 1, r, ql, qr); 107 a[id] = a[id << 1] + a[id << 1 | 1]; 108 } 109 }seg; 110 111 int main() 112 { 113 while (scanf("%d%d%d", &n, &k, &m) != EOF) 114 { 115 for (int i = 1; i <= m; ++i) que[i].scan(); 116 sort(que + 1, que + 1 + m); 117 seg.build(1, 1, n); 118 ll res = 0; 119 for (int i = 1, l, r, c, p; i <= m; ++i) 120 { 121 l = que[i].l, r = que[i].r, c = que[i].c, p = que[i].p; 122 while (1) 123 { 124 seg.res.init(); 125 seg.query(1, 1, n, l, r); 126 if (seg.res.cnt == 0) break; 127 if (seg.res.Min <= c) 128 { 129 res += (ll)p * seg.res.Min; 130 seg.update(1, 1, n, seg.res.pos); 131 } 132 else 133 { 134 res += (ll)p * seg.res.cnt * c; 135 seg.update(1, 1, n, l, r, -c); 136 break; 137 } 138 } 139 } 140 printf("%lld\n", res); 141 } 142 return 0; 143 }
D. Garbage Disposal
水。
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 typedef long long ll; 6 7 int main() 8 { 9 ll n, k; 10 while(~scanf("%lld %lld", &n, &k)) 11 { 12 ll ans = 0; 13 ll res = 0; 14 for(int i = 1; i <= n; ++i) 15 { 16 ll x; 17 scanf("%lld", &x); 18 if(res > 0) 19 { 20 res += x; 21 if(res >= k) 22 { 23 ans += res / k; 24 res %= k; 25 } 26 else 27 { 28 res = 0; 29 ans++; 30 } 31 } 32 else 33 { 34 res += x; 35 ans += res / k; 36 res %= k; 37 } 38 } 39 if(res) 40 { 41 ans += res % k == 0 ? res / k : res / k + 1; 42 } 43 printf("%lld\n", ans); 44 } 45 return 0; 46 }
E. Getting Deals Done
Solved By 2017212212083 & Dup4
题意:
有一个任务序列,每个任务有一个完成时间,在做任务的时候有这样一个规则,定义一个d,对于所有时间小于等于d的任务都要做,并且每做完m个,都要休息,休息时间为这m个任务的总时间,如果一个任务做不完,这个任务不算数。给出一个总时间T, n, m
以及每个任务的时间,求最大的任务数,以及d
思路:
二分任务数x, 显然我们要做的任务是排序后前x个,将d设为第x个的时间,按规则遍历看是否合法即可。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define ll long long 5 #define N 200010 6 int t, n, m; ll T; 7 int p[N], b[N]; 8 9 bool check(int x) 10 { 11 int dd = p[x]; 12 ll tmp = 0, TT = T; int cnt = 0, tot = 0; 13 for (int i = 1; i <= n; ++i) if (b[i] <= dd) 14 { 15 if (TT - b[i] >= 0) 16 { 17 ++cnt; TT -= b[i]; 18 tmp += b[i]; 19 ++tot; 20 } 21 else return tot >= x; 22 if (cnt == m) 23 { 24 cnt = 0; 25 TT -= tmp; 26 tmp = 0; 27 } 28 } 29 if (tot >= x) 30 { 31 return true; 32 } 33 return false; 34 } 35 36 int main() 37 { 38 scanf("%d", &t); 39 while (t--) 40 { 41 scanf("%d%d%lld", &n, &m, &T); 42 for (int i = 1; i <= n; ++i) scanf("%d", p + i), b[i] = p[i]; 43 sort(p + 1, p + 1 + n); 44 p[0] = T; 45 int l = 0, r = n, res = -1; 46 while (r - l >= 0) 47 { 48 int mid = (l + r) >> 1; 49 if (check(mid)) 50 { 51 res = mid; 52 l = mid + 1; 53 } 54 else 55 r = mid - 1; 56 } 57 printf("%d %d\n", res, p[res]); 58 } 59 return 0; 60 }
F. Debate
水。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define N 400010 5 int n, a[N], cnt[4]; 6 priority_queue <int> pq[4]; 7 8 void init() 9 { 10 memset(cnt, 0, sizeof cnt); 11 for (int i = 0; i < 4; ++i) while (!pq[i].empty()) pq[i].pop(); 12 } 13 14 int main() 15 { 16 while (scanf("%d", &n) != EOF) 17 { 18 init(); int res = 0; 19 for (int i = 1, x; i <= n; ++i) 20 { 21 scanf("%02d%d", &x, a + i); 22 if (x == 11) x = 3; 23 else if (x == 10) x = 2; 24 ++cnt[x]; 25 if (x == 3) res += a[i]; 26 else pq[x].push(a[i]); 27 } 28 int limit = min(cnt[1], cnt[2]); 29 for (int i = 1; i <= 2; ++i) for (int j = 0; j < limit; ++j) 30 { 31 res += pq[i].top(); pq[i].pop(); 32 } 33 for (int i = 1; i <= 2; ++i) while (!pq[i].empty()) 34 { 35 pq[0].push(pq[i].top()); pq[i].pop(); 36 } 37 limit = min(cnt[3], (int)pq[0].size()); 38 for (int i = 0; i < limit; ++i) 39 { 40 res += pq[0].top(); pq[0].pop(); 41 } 42 printf("%d\n", res); 43 } 44 return 0; 45 }
G. Monsters and Potions
Unsolved.
H. BerOS File Suggestion
水。
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 map<string, int>mp1; 6 map<string, string>mp2; 7 8 int n, q; 9 string s; 10 11 int main() 12 { 13 ios::sync_with_stdio(false); 14 cin.tie(0); 15 cout.tie(0); 16 while(cin >> n) 17 { 18 mp1.clear(); 19 mp2.clear(); 20 for(int i = 1; i <= n; ++i) 21 { 22 cin >> s; 23 int len = s.length(); 24 set<string>st; 25 for(int i = 0; i < len; ++i) 26 { 27 string tmp = ""; 28 for(int j = i; j < len; ++j) 29 { 30 tmp += s[j]; 31 st.insert(tmp); 32 } 33 } 34 for(auto it : st) 35 { 36 mp1[it]++; 37 mp2[it] = s; 38 } 39 } 40 cin >> q; 41 while(q--) 42 { 43 cin >> s; 44 cout << mp1[s] << " "; 45 if(mp1[s]) 46 { 47 cout << mp2[s] << "\n"; 48 } 49 else 50 { 51 cout << "-\n"; 52 } 53 } 54 } 55 return 0; 56 }
I. Privatization of Roads in Berland
Unsolved.
J. Streets and Avenues in Berhattan
Unsolved.
K. Video Posts
水。
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 const int maxn = 1e5 + 10; 6 7 int n, k; 8 int arr[maxn]; 9 int sum; 10 11 void solve() 12 { 13 if(sum % k) 14 { 15 puts("No"); 16 return ; 17 } 18 vector<int>vec; 19 int res = 0; 20 int st = 0; 21 for(int i = 1; i <= n; ++i) 22 { 23 res += arr[i]; 24 if(res > sum / k) 25 { 26 puts("No"); 27 return ; 28 } 29 else if(res == sum / k) 30 { 31 vec.push_back(i - st); 32 st = i; 33 res = 0; 34 } 35 } 36 puts("Yes"); 37 for(int i = 0, len = vec.size(); i < len; ++i) 38 { 39 printf("%d%c", vec[i], " \n"[i == len - 1]); 40 } 41 } 42 43 int main() 44 { 45 while(~scanf("%d %d", &n ,&k)) 46 { 47 sum = 0; 48 for(int i = 1; i <= n; ++i) 49 { 50 scanf("%d", arr + i); 51 sum += arr[i]; 52 } 53 solve(); 54 } 55 return 0; 56 }
L. Odd Federalization
Unsolved.
M. Algoland and Berland
Unsolved.