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 }
A. Packets

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 }
B. Reach Median

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 }
C. Equalize

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 }
D. Valid BFS?

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 }
E. Trips

posted @ 2018-09-03 19:30  KingSann  阅读(206)  评论(0编辑  收藏  举报