简单小结:
A题
先找出每个城市中得票最高的
然后再在以上求出的那帮人中出一个得票(一个城市只算一票)中最高的
1 /*********************************** 2 * * 3 * Auther Rhapsody * 4 * E-mail [email protected] * 5 * * 6 ***********************************/ 7 #include <set> 8 #include <map> 9 #include <cmath> 10 #include <deque> 11 #include <queue> 12 #include <vector> 13 #include <cstdio> 14 #include <cstdlib> 15 #include <cstring> 16 #include <iostream> 17 #include <algorithm> 18 19 #define MP make_pair 20 #define PB push_back 21 22 using namespace std; 23 24 typedef long long LL; 25 typedef pair<int, int> PII; 26 27 const int N = 1e2 + 7; 28 const int INF = 0x3f3f3f3f; 29 const int MOD = 1e9 + 7; 30 31 int a[N][N]; 32 33 int cnt[N]; 34 35 int main(void) { 36 int n, m; 37 scanf("%d%d", &n, &m); 38 for (int i = 1; i <= m; ++i) { 39 for (int j = 1; j <= n; ++j) { 40 scanf("%d", &a[i][j]); 41 } 42 } 43 for (int i = 1; i <= m; ++i) { 44 int k = 1; 45 for (int j = 2; j <= n; ++j) 46 if (a[i][j] > a[i][k]) 47 k = j; 48 a[i][0] = k; 49 } 50 for (int i = 1; i <= m; ++i) { 51 ++cnt[a[i][0]]; 52 } 53 int Ans = 1; 54 for (int i = 1; i <= n; ++i) 55 if (cnt[Ans] < cnt[i]) 56 Ans = i; 57 cout << Ans << endl; 58 return 0; 59 }
B题
我们可以画一个图,画一个坐标轴
我们很显然的可以看出,a=c-1或者a=c+1两者必有一个是最佳答案
1 /*********************************** 2 * * 3 * Auther Rhapsody * 4 * E-mail [email protected] * 5 * * 6 ***********************************/ 7 #include <set> 8 #include <map> 9 #include <cmath> 10 #include <deque> 11 #include <queue> 12 #include <vector> 13 #include <cstdio> 14 #include <cstdlib> 15 #include <cstring> 16 #include <iostream> 17 #include <algorithm> 18 19 #define MP make_pair 20 #define PB push_back 21 22 using namespace std; 23 24 typedef long long LL; 25 typedef pair<int, int> PII; 26 27 const int N = 1e5 + 7; 28 const int INF = 0x3f3f3f3f; 29 const int MOD = 1e9 + 7; 30 31 int main(void) { 32 int n, m; 33 scanf("%d%d", &n, &m); 34 int l = m - 1, r = m + 1; 35 if (n == 1) { 36 cout << 1 << endl; 37 return 0; 38 } 39 if (l == 0) { 40 cout << r << endl; 41 return 0; 42 } 43 if (r > n) { 44 cout << l << endl; 45 return 0; 46 } 47 if (l >= n - m) 48 cout << l << endl; 49 else 50 cout << r << endl; 51 return 0; 52 }
C题
首先对于初始的那个串,我们可以通过一次扫描把最初始的答案求出
具体做法就是找到一个长度为l的连续的“...”串,那么答案就+(l-1)
我们可以通过分类讨论
先讨论用‘.’替换‘.’:并没有什么卵用
同理用字母替换字母:也没有什么卵用
用‘.’替换字母:如果左边也是‘.’那么我们统计的那个答案就可以+1了,同理右边如果也是‘.’那么我们就答案+1
用字母替换‘.’:如果旁边有一个‘.’那么答案就-1
通过以上讨论进行及时的计算
1 /*********************************** 2 * * 3 * Auther Rhapsody * 4 * E-mail [email protected] * 5 * * 6 ***********************************/ 7 #include <set> 8 #include <map> 9 #include <cmath> 10 #include <deque> 11 #include <queue> 12 #include <vector> 13 #include <cstdio> 14 #include <cstdlib> 15 #include <cstring> 16 #include <iostream> 17 #include <algorithm> 18 19 #define MP make_pair 20 #define PB push_back 21 22 using namespace std; 23 24 typedef long long LL; 25 typedef pair<int, int> PII; 26 27 const int N = 3e5 + 7; 28 const int INF = 0x3f3f3f3f; 29 const int MOD = 1e9 + 7; 30 31 bool c[N]; 32 33 char s[N]; 34 35 int main(void) { 36 int n, m; 37 scanf("%d%d", &n, &m); 38 scanf("%s", s + 1); 39 int Ans = 0; 40 for (int i = 1; i <= n; ++i) { 41 if (s[i] == ‘.‘) 42 c[i] = true; 43 else 44 c[i] = false; 45 if (s[i] == ‘.‘ && s[i - 1] == ‘.‘) 46 ++Ans; 47 } 48 //cout << Ans << endl; 49 while (m--) { 50 int x; 51 char ch; 52 scanf("%d %c", &x, &ch); 53 if (ch == ‘.‘ && !c[x]) { 54 c[x] = true; 55 if (x > 1 && c[x - 1]) 56 ++Ans; 57 if (x < n && c[x + 1]) 58 ++Ans; 59 } 60 if (ch != ‘.‘ && c[x]) { 61 c[x] = false; 62 if (x > 1 && c[x - 1]) 63 --Ans; 64 if (x < n && c[x + 1]) 65 --Ans; 66 } 67 printf("%d\n", Ans); 68 } 69 return 0; 70 }
D题
感觉题出的真心很不错
题目大意就是,给你一棵有根树(节点数量500000级别),每个节点上面都有一个字母,然后给你一定询问(500000级别)
每次询问<v, h>就是问你v这个节点的子树中深度为h的所有节点上的字母是否能够组成为一个回文串
首先字母只有小写的26个字母
这一堆字母能不能构成回文串的因素就是这26个字母的出现次数最多只能有一个是偶数
如果是问一个字符串,询问某个连续的子串如果打乱顺序的话是否能够构成一个回文串
那么我们只需要开一个sum记录这个字符串的每个字母出现次数的前缀和即可
但是问题是这个是在一个树上了,那么我们可以利用dfs序来解决这个问题,把树转化为链,对于深度问题,我们只需要把每个深度的点放在一起,然后用二分查找的方法就可以解决这个问题
1 /*********************************** 2 * * 3 * Auther Rhapsody * 4 * E-mail [email protected] * 5 * * 6 ***********************************/ 7 #include <set> 8 #include <map> 9 #include <cmath> 10 #include <deque> 11 #include <queue> 12 #include <vector> 13 #include <cstdio> 14 #include <cstdlib> 15 #include <cstring> 16 #include <iostream> 17 #include <algorithm> 18 19 #define MP make_pair 20 #define PB push_back 21 22 using namespace std; 23 24 typedef long long LL; 25 typedef pair<int, int> PII; 26 27 const int N = 5e5 + 7; 28 const int INF = 0x3f3f3f3f; 29 const int MOD = 1e9 + 7; 30 31 vector <int> e[N]; 32 33 vector <PII> head[N]; 34 35 char s[N]; 36 37 int in[N], out[N], pos; 38 39 void dfs(int u, int d) { 40 //printf("Dfs : %d %d\n", u, d); 41 in[u] = ++pos; 42 for (int i = 0; i < e[u].size(); ++i) { 43 int v = e[u][i]; 44 dfs(v, d + 1); 45 } 46 head[d].PB(MP(u, 0)); 47 out[u] = pos; 48 } 49 50 void deal(vector <PII> &data) { 51 //printf("Deal : \n"); 52 for (int i = 1; i < data.size(); ++i) { 53 data[i].second = data[i - 1].second; 54 data[i].second ^= 1 << (s[data[i].first] - ‘a‘); 55 //printf("%d %d\n", data[i].first, data[i].second); 56 } 57 } 58 59 int find(int k, vector <PII> &data) { 60 //printf("Aim is %d\n", k); 61 int l = 0, r = data.size() - 1; 62 while (l < r) { 63 int mid = ((l + r) >> 1) + 1; 64 if (in[data[mid].first] <= k) 65 l = mid; 66 else 67 r = mid - 1; 68 } 69 return l; 70 } 71 72 bool judge(int x) { 73 return (x & (x - 1)) == 0; 74 } 75 76 bool ask(int u, vector <PII> &data) { 77 //printf("Ask : %d\n", u); 78 int r = find(out[u], data), l = find(in[u] - 1, data); 79 //printf("Get %d %d\n", l, r); 80 //printf("R = %d\n", data[r].first); 81 if (in[u] > in[data[r].first] || out[u] < in[data[r].first]) return true; 82 return judge(data[l].second ^ data[r].second); 83 } 84 85 int main(void) { 86 int n, Q; 87 scanf("%d%d", &n, &Q); 88 for (int i = 2; i <= n; ++i) { 89 int u; 90 scanf("%d", &u); 91 e[u].PB(i); 92 } 93 for (int i = 1; i <= n; ++i) 94 head[i].PB(MP(0, 0)); 95 dfs(1, 1); 96 scanf("%s", s + 1); 97 for (int i = 1; i <= n; ++i) { 98 //printf("Deal : %d\n", i); 99 deal(head[i]); 100 } 101 while (Q--) { 102 int v, h; 103 scanf("%d%d", &v, &h); 104 //printf("Ask : %d %d\n", v, h); 105 if (ask(v, head[h])) 106 puts("Yes"); 107 else 108 puts("No"); 109 } 110 return 0; 111 }
E题
DP,对角线优化+滚动数组
何为对角线优化?
如我我们想到了动态规划,我们最开始可以有这样的想法:f[i][j][k][l]
代表开头在i, j结尾再k, l的位置的方案数
我们仔细发现,i + j与k + l有什么关系呢?
我们可以画一画矩阵的对角线来理解理解
i + j + k + l == n + m + 2
所以带上你的滚动数组AC吧
1 /*********************************** 2 * * 3 * Auther Rhapsody * 4 * E-mail [email protected] * 5 * * 6 ***********************************/ 7 #include <set> 8 #include <map> 9 #include <cmath> 10 #include <deque> 11 #include <queue> 12 #include <vector> 13 #include <cstdio> 14 #include <cstdlib> 15 #include <cstring> 16 #include <iostream> 17 #include <algorithm> 18 19 #define MP make_pair 20 #define PB push_back 21 22 using namespace std; 23 24 typedef long long LL; 25 typedef pair<int, int> PII; 26 27 const int N = 512; 28 const int INF = 0x3f3f3f3f; 29 const int MOD = 1e9 + 7; 30 31 char s[N][N]; 32 33 int f[2][N][N]; 34 35 int main(void) { 36 int n, m; 37 scanf("%d%d", &n, &m); 38 for (int i = 1; i <= n; ++i) { 39 scanf("%s", s[i] + 1); 40 } 41 int h = n + m + 2; 42 if ((n + m) & 1) { 43 int k = h >> 1; 44 for (int i = 1; i <= n; ++i) { 45 int j = k - i; 46 if (j <= 0 || j > m) continue; 47 for (int u = 1; u <= n; ++u) { 48 int v = h - k - u; 49 if (v <= 0 || v > m) continue; 50 if (s[i][j] == s[u][v] && abs(i - u) + abs(j - v) == 1) 51 f[k & 1][i][u] = 1; 52 } 53 } 54 } else { 55 int k = h >> 1; 56 for (int i = 1; i <= n; ++i) 57 f[k & 1][i][i] = 1; 58 } 59 for (int k = h / 2 - 1; k >= 2; --k) { 60 int op = k & 1; 61 for (int i = 1; i <= n; ++i) { 62 int j = k - i; 63 if (j <= 0 || j > m) continue; 64 for (int u = 1; u <= n; ++u) { 65 int v = h - k - u; 66 if (v <= 0 || v > m) continue; 67 if (s[i][j] != s[u][v]) { 68 f[op][i][u] = 0; 69 continue; 70 } 71 f[op][i][u] = (f[op ^ 1][i][u] + f[op ^ 1][i + 1][u]) % MOD + (f[op ^ 1][i][u - 1] + f[op ^ 1][i + 1][u - 1]) % MOD; 72 f[op][i][u] %= MOD; 73 } 74 } 75 } 76 printf("%d\n", f[0][1][n]); 77 return 0; 78 }