codeforces #1037 A B C D E
A. Packets
给定$n$,你可以打造一些面值在$[1,n]$的硬币(面值是整数)
求至少打造多少个硬币,使得可以凑出$[1,n]$中所有整数面额
$1 \le n \le 10^9$
小学老师告诉我们,可以通过$1,2,4,8,16 \dots$这些$2$的整次幂来凑出一个十进制数
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 5 int main() { 6 ll n; cin >> n; 7 ll k = 0; 8 while(2 * (1 << (k + 1)) - 1 <= n) ++ k; 9 ll ans = k + 1 + ((n - (2 * (1 << (k)) - 1)) > 0); 10 cout << ans << endl; 11 }
B. Reach Median
有一个长度为$n$的序列,给定一个数字$S$
每次可以选择一个位置,并将它加上$1$或者减去$1$
假设一共操作$x$次,操作完之后求这个序列的中位数(保证$n$是奇数)
要求这个中位数为$S$
最小化操作次数
$1 \le n \le 2 \times 10^5-1$
$1 \le S \le 10^9$
初中老师告诉我们,将序列排序后让中位数变为$S$是最优的选择
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int N = 2e5 + 10; 5 int n, s, a[N]; 6 ll ans; 7 int main() { 8 cin >> n >> s; 9 for(int i = 1 ; i <= n ; ++ i) cin >> a[i]; 10 sort(a + 1, a + 1 + n); 11 for(int i = 1 ; i <= n / 2 ; ++ i) { 12 if(a[i] > s) ans += a[i] - s; 13 if(a[n - i + 1] < s) ans += s - a[n - i + 1]; 14 } 15 ans += abs(a[n / 2 + 1] - s); 16 printf("%lld\n", ans); 17 }
C. Equalize
给定两个长度为$n$的$01$序列$a,b$
每次可以执行如下操作:
1. 在$a$中选择一个位置$p$,将$a_p$变为$1-a_p$,代价是$1$
2. 在$a$中选择两个位置$p,q$,将$a_p$和$a_q$互换,代价是$\mid p-q \mid$
要求将$a$变成$b$,最小化代价
$1 \le n \le 10^6$
高中老师告诉我们,经过手玩之后,可以发现:对于操作$1$只在交换相邻两个位置的时候有用
于是可以直接$O(n)$的扫一遍,如果$i$和$i+1$都没有匹配上,且$a_i \not= a_{i+1}$,那么就交换这俩
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int N = 1e6 + 10; 5 int n, x[N]; 6 char a[N], b[N]; 7 int main() { 8 cin >> n; 9 cin >> (a + 1) >> (b + 1); 10 int ans = 0; 11 for(int i = 1 ; i <= n ; ++ i) { 12 if(i + 1 <= n && a[i] != b[i] && a[i + 1] != b[i + 1] && a[i] != a[i + 1]) { 13 ans += 1; 14 ++ i; 15 } else { 16 ans += a[i] != b[i]; 17 } 18 } 19 printf("%d\n", ans); 20 }
D. Valid BFS?
给你一棵根为$1$的树,同时给定一个$bfs$序列
判断这个$bfs$序是否是这棵树的$bfs$序
$1 \le n \le 2 \times 10^5$
对于每一个点,可以直接用$map$存一下这个点的儿子,然后$O(n)$的扫一遍$bfs$序,判断能否加入节点
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int N = 2e5 + 10; 5 map<int, int> g[N]; 6 vector<int> mp[N]; 7 int n, a[N], vis[N]; 8 void dfs(int u, int fa) { 9 for(int v: mp[u]) 10 if(v != fa) 11 g[u][v] = 1, dfs(v, u); 12 } 13 void WA() { 14 puts("No"); 15 exit(0); 16 } 17 int main() { 18 cin >> n; 19 for(int i = 1, u, v ; i < n ; ++ i) { 20 cin >> u >> v; 21 mp[u].push_back(v); 22 mp[v].push_back(u); 23 } 24 dfs(1, 0); 25 for(int i = 1 ; i <= n ; ++ i) scanf("%d", &a[i]); 26 if(a[1] != 1) WA(); 27 queue<int> q; 28 q.push(1); 29 int p = 2; 30 while(q.size()) { 31 int u = q.front(); q.pop(); vis[u] = 1; 32 while(p <= n && g[u].find(a[p]) != g[u].end()) { 33 q.push(a[p]); 34 ++ p; 35 } 36 } 37 for(int i = 1 ; i <= n ; ++ i) if(!vis[i]) WA(); 38 puts("Yes"); 39 }
E. Trips
有$n$个人,经历了$m$天,同时给定一个常数$k$
第$i$天早晨,$x_i$和$y_i$会成为朋友(朋友没有传递性)
每天晚上会举办一个晚会
第$i$天晚上,如果一个人有$k$个朋友都参加,那么这个人也会去参加
问每天最多会有多少人参加
$2 \le n \le 2 \times 10^5$
$1 \le m \le 2 \times 10^5$
$1 \le k \lt n$
将操作反过来做,这样的话就是只有删除的问题了,用$set$维护$(deg_u,u)$即可
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int N = 2e5 + 10; 5 struct E { int u, v, time; } e[N]; 6 int deg[N], ans[N], inq[N], n, m, k; 7 set<pair<int, int> > s; 8 vector<pair<int, int> > g[N]; 9 10 int main() { 11 cin >> n >> m >> k; 12 for(int i = 1 ; i <= m ; ++ i) { 13 int u, v, time = i; 14 cin >> u >> v; 15 e[i] = (E) { u, v, time }; 16 g[u].push_back(make_pair(v, time)), g[v].push_back(make_pair(u, time)); 17 ++ deg[u], ++ deg[v]; 18 } 19 for(int i = 1 ; i <= n ; ++ i) s.insert(make_pair(deg[i], i)), inq[i] = 1; 20 while(s.size() && s.begin() -> first < k) { 21 int u = s.begin() -> second; s.erase(s.begin()); 22 inq[u] = 0; 23 for(auto e: g[u]) { 24 int v = e.first; 25 if(inq[v]) { 26 s.erase(make_pair(deg[v], v)); 27 -- deg[v]; 28 s.insert(make_pair(deg[v], v)); 29 } 30 } 31 } 32 for(int i = m - 1 ; ~ i ; -- i) { 33 ans[i] = s.size(); 34 int u = e[i + 1].u, v = e[i + 1].v; 35 if(inq[u] && inq[v]) { 36 s.erase(make_pair(deg[u], u)); 37 s.erase(make_pair(deg[v], v)); 38 -- deg[u], -- deg[v]; 39 s.insert(make_pair(deg[u], u)); 40 s.insert(make_pair(deg[v], v)); 41 } 42 while(s.size() && s.begin() -> first < k) { 43 int u = s.begin() -> second; s.erase(s.begin()); 44 inq[u] = 0; 45 for(auto e: g[u]) { 46 int v = e.first, time = e.second; 47 if(time <= i && inq[v]) { 48 s.erase(make_pair(deg[v], v)); 49 -- deg[v]; 50 s.insert(make_pair(deg[v], v)); 51 } 52 } 53 } 54 } 55 for(int i = 0 ; i < m ; ++ i) cout << ans[i] << endl; 56 }