A.容易发现最后字符的对应都是一对一的
或者说我们没办法出现最后多对一或者一对多的情况
所以只要算出 ‘a’ - 'z' 每个字符最后对应的字符即可
1 #include <cstdio> 2 #include <algorithm> 3 4 int n, m, b[26]; 5 6 char a[26], s[200010]; 7 8 int main() { 9 char s1[5], s2[5]; 10 scanf("%d %d %s", &n, &m, s); 11 for(int i = 0;i < 26;i ++) a[i] = i + 'a', b[i] = i; 12 while(m --) { 13 scanf("%s %s", s1, s2); 14 if(s1[0] == s2[0]) continue; 15 a[b[s1[0] - 'a']] = s2[0]; 16 a[b[s2[0] - 'a']] = s1[0]; 17 std::swap(b[s1[0] - 'a'], b[s2[0] - 'a']); 18 } 19 for(int i = 0;i < n;i ++) 20 putchar(a[s[i] - 'a']); 21 return 0; 22 }
B.
C.A simple directed graph is a directed graph having no multiple edges or graph loops.
graph loops其实说的是自环?道理我都懂,但是自环不是self loops之类的吗?
我们考虑连完所有边的最终形态,应该是
两个强连通分量AB,内部均为完全图
A中所有点都能到B中所有点
B中没有连向A中点的边
稍微算一下可知令siz_A与siz_B差距越大,可连边就越多
那我们先对原图求强连通分量
这里面没有入度或没有出度的scc是有可能成为A或B的scc
找出这里面siz最小的scc来确定A和B其中一个的siz即可
为什么不可能是siz最大的一个呢?
我们列一下式子发现时恒等式
siz最小的必然不比siz最大的结果差
#include <bits/stdc++.h> using namespace std; const int maxn = 100010; int n, m, cnt, top, sum, c1[maxn], c2[maxn], siz[maxn]; int in[maxn], vis[maxn], sta[maxn], dfn[maxn], low[maxn], bel[maxn]; vector <int> e[maxn]; void tarjan(int x) { vis[x] = 1; in[x] = 1, sta[++ top] = x, dfn[x] = low[x] = ++ cnt; for(int t, i = 0;i < e[x].size();i ++) { t = e[x][i]; if(!vis[t]) { tarjan(t); low[x] = min(low[x], low[t]); } else if(in[t] && low[t] < low[x]) low[x] = low[t]; } if(low[x] == dfn[x]) { sum ++; for(int i = 0;i != x;i = sta[top --], bel[i] = sum, in[i] = 0, siz[sum] ++); } } int main() { long long ans; int Case, u, v, tmp; ios::sync_with_stdio(false); cin >> Case; for(int tt = 1;tt <= Case;tt ++) { cout << "Case " << tt << ": "; cin >> n >> m; cnt = ans = sum = 0, tmp = n; for(int i = 1;i <= n;i ++) e[i].clear(), vis[i] = c1[i] = c2[i] = siz[i] = 0; for(int i = 1;i <= m;i ++) cin >> u >> v, e[u].push_back(v); for(int i = 1;i <= n;i ++) if(!vis[i]) tarjan(i); if(sum == 1) cout << -1 << endl; else { for(int i = 1;i <= n;i ++) for(int j = 0;j < e[i].size();j ++) if(bel[i] != bel[e[i][j]]) c1[bel[i]] ++, c2[bel[e[i][j]]] ++; for(int i = 1;i <= sum;i ++) if(c1[i] == 0 || c2[i] == 0) tmp = min(tmp, siz[i]); cout << 1ll * n * n - m - n - 1ll * tmp * (n - tmp) << endl; } } }
D.其实只要先处理出昨天没走的人
就可以算出今天各个时刻的人数了,取max即可
1 #include <iostream> 2 3 using namespace std; 4 5 bool in[1000010]; 6 7 int n, ans, cnt, x; 8 9 char str[110][3]; 10 11 int main() { 12 ios::sync_with_stdio(false); 13 cin >> n; 14 for(int i = 1;i <= n;i ++) { 15 cin >> str[i] >> x; 16 if(str[i][0] == '+') in[x] = 1; 17 else if(!in[x]) cnt ++; 18 } 19 ans = cnt; 20 for(int i = 1;i <= n;i ++) { 21 if(str[i][0] == '+') cnt ++, ans = max(cnt, ans); 22 else cnt --; 23 } 24 cout << ans; 25 }
E.我们令第 i 个数为 a[i]
计算出以 a[i] 为序列第一个数的方案种数
以 a[i] 为序列第二个数的方案种数
ans += 以 a[i] / k 为序列第二个数的方案种数
1 #include <map> 2 #include <iostream> 3 4 using namespace std; 5 6 typedef long long ll; 7 8 map <ll, ll> p[2]; 9 10 int n, k; 11 12 int a[200010]; 13 14 ll ans; 15 16 int main() { 17 ios::sync_with_stdio(false); 18 cin >> n >> k; 19 for(int i = 1;i <= n;i ++) { 20 cin >> a[i]; 21 if(a[i] % k == 0) ans += p[1][a[i] / k], p[1][a[i]] += p[0][a[i] / k]; 22 p[0][a[i]] ++; 23 } 24 cout << ans; 25 return 0; 26 }
F.
G.先缩点
1 #include <queue> 2 #include <vector> 3 #include <cstring> 4 #include <iostream> 5 6 using namespace std; 7 8 const int maxn = 100010; 9 10 struct node{ 11 int x, y; 12 bool operator < (const node &a) const { 13 return y > a.y; 14 } 15 }; 16 17 vector <node> e[maxn], f[maxn]; 18 19 priority_queue <node> q; 20 21 int n, N, m, vi[maxn]; 22 23 long long ans; 24 25 int cnt, top, in[maxn], dfn[maxn], low[maxn], sta[maxn], vis[maxn], bel[maxn], sum[maxn]; 26 27 void Clear() { 28 ans = cnt = N = 0; 29 for(int i = 0;i < n;i ++) e[i].clear(), f[i].clear(), vi[i] = vis[i] = 0; 30 while(!q.empty()) q.pop(); 31 } 32 33 void tarjan(int x, int t = 0) { 34 vis[x] = 1; 35 dfn[x] = low[x] = ++ cnt, sta[++ top] = x, in[x] = 1; 36 for(int i = 0;i < e[x].size();i ++) { 37 t = e[x][i].x; 38 if(!vis[t]) { 39 tarjan(t); 40 low[x] = min(low[x], low[t]); 41 } 42 else if(in[t] && low[t] < low[x]) low[x] = low[t]; 43 } 44 if(low[x] == dfn[x]) { 45 for(int i = -1;i != x;i = sta[top --], bel[i] = N, in[i] = 0); 46 N ++; 47 } 48 } 49 50 int main() { 51 ios::sync_with_stdio(false); 52 int u, v, w; 53 node tmp; 54 while(cin >> n >> m) { 55 Clear(); 56 for(int i = 1;i <= m;i ++) 57 cin >> u >> v >> w, e[u].push_back((node){v, w}); 58 for(int i = 0;i < n;i ++) 59 if(!vis[i]) tarjan(i); 60 memset(sum, 0x3f,sizeof sum); 61 for(int i = 0;i < n;i ++) { 62 for(int j = 0;j < e[i].size();j ++) 63 if(bel[i] != bel[e[i][j].x]) 64 sum[bel[e[i][j].x]] = min(sum[bel[e[i][j].x]], e[i][j].y); 65 } 66 for(int i = 0;i < N;i ++) 67 if(sum[i] != 0x3f3f3f3f) 68 ans += sum[i]; 69 cout << ans << endl; 70 } 71 return 0; 72 }
H.手写一下发现总共只有2 + 4 + 8 + ... + 2^9 = 1022 个数
所以枚举对比一下就好了
1 #include <vector> 2 #include <iostream> 3 4 using namespace std; 5 6 vector <int> e[10]; 7 8 int n, sum; 9 10 int main() { 11 e[0].push_back(0); 12 cin >> n; 13 for(int i = 1, j = 1;i <= 9;i ++, j *= 10) { 14 for(int t, k = 0;k < e[i - 1].size();k ++) { 15 t = 4 * j + e[i - 1][k]; 16 e[i].push_back(t); 17 if(t == n) { 18 cout << sum + e[i].size(); 19 return 0; 20 } 21 } 22 for(int t, k = 0;k < e[i - 1].size();k ++) { 23 t = 7 * j + e[i - 1][k]; 24 e[i].push_back(t); 25 if(t == n) { 26 cout << sum + e[i].size(); 27 return 0; 28 } 29 } 30 sum += e[i].size(); 31 } 32 }