2020国庆清北学堂Day1解题报告
A 打扑克:
显然需要将 个数奇偶与先手是谁 分成四部分讨论
容易得到 偶个数偶先手偶必胜 与 奇个数奇先手奇必胜 的结论
那么剩下两个 case 呢?
容易得到 偶个数奇先手偶必胜,毕竟奇永远比偶少1
同时可以手玩得到 奇个数偶先手偶必胜,因为偶数掌握牌权的同时奇数有一个必白给的1
注意特判两张牌的情况
1 #include <ctime> 2 #include <cmath> 3 #include <cstdio> 4 #include <cstring> 5 #include <cstdlib> 6 #include <iostream> 7 #include <algorithm> 8 #include <vector> 9 #include <queue> 10 #define inf 100010 11 #define INF 0x7fffffff 12 #define ll long long 13 14 namespace chiaro{ 15 16 template <class I> 17 inline void read(I &num){ 18 num = 0; char c = getchar(), up = c; 19 while(c < '0' || c > '9') up = c, c = getchar(); 20 while(c >= '0' && c <= '9') num = (num << 1) + (num << 3) + (c ^ '0'), c = getchar(); 21 up == '-' ? num = -num : 0; return; 22 } 23 template <class I> 24 inline void read(I &a, I &b) {read(a); read(b);} 25 template <class I> 26 inline void read(I &a, I &b, I &c) {read(a); read(b); read(c);} 27 28 inline void solve () { 29 char c = getchar(), up = c; 30 int len = 0; 31 while(!isdigit(c)) c = getchar(); 32 while(isdigit(c)) ++len, up = c, c = getchar(); 33 int o; read(o); 34 int n = up - '0'; o = !o; 35 if(len == 1 && n == 2) { 36 printf("%d\n", !o); 37 return; 38 } 39 int win = 0; 40 if((o & 1) && (n & 1)) win = 0; 41 else if((o & 1) == 0 && (n & 1) == 0) win = 1; 42 else win = 1; 43 printf("%d\n", win); 44 } 45 46 inline int main(){ 47 int T; read(T); 48 while(T--) solve(); 49 return 0; 50 } 51 52 } 53 54 signed main(){ return chiaro::main();}
B. 粉刷匠
可以发现,一个位置归属于谁只取决于最后一次覆盖到他的操作,所以可以考虑到倒着进行操作
已覆盖的位置不可能再被覆盖,直接对于覆盖成 1 的操作统计答案即可
1 #include <ctime> 2 #include <cmath> 3 #include <cstdio> 4 #include <cstring> 5 #include <cstdlib> 6 #include <iostream> 7 #include <algorithm> 8 #include <vector> 9 #include <queue> 10 #define inf 1000010 11 #define INF 0x7fffffff 12 #define ll long long 13 14 namespace chiaro{ 15 16 template <class I> 17 inline void read(I &num){ 18 num = 0; char c = getchar(), up = c; 19 while(c < '0' || c > '9') up = c, c = getchar(); 20 while(c >= '0' && c <= '9') num = (num << 1) + (num << 3) + (c ^ '0'), c = getchar(); 21 up == '-' ? num = -num : 0; return; 22 } 23 template <class I> 24 inline void read(I &a, I &b) {read(a); read(b);} 25 template <class I> 26 inline void read(I &a, I &b, I &c) {read(a); read(b); read(c);} 27 28 int n[2]; 29 int q; 30 int x[inf], y[inf], z[inf]; 31 bool vis[2][inf]; 32 33 inline int main(){ 34 read(n[0], n[1], q); 35 for(int i = 1; i <= q; i++) read(x[i], y[i], z[i]); 36 ll ans = 0; 37 for(int i = q; i; --i) { 38 if(vis[x[i]][y[i]]) continue; 39 vis[x[i]][y[i]] = 1; 40 if(z[i]) ans += n[!x[i]]; 41 --n[x[i]]; 42 } 43 printf("%lld\n", ans); 44 return 0; 45 } 46 47 } 48 49 signed main(){ return chiaro::main();}
C. 直线竞速
考虑优化暴力,容易知道关键在于怎样快速求得区间不排序第 k 大
可以使用分治,同时 algorithm 库中的 STL 函数 std::nth_element() 可以直接完成这步操作
1 #include <ctime> 2 #include <cmath> 3 #include <cstdio> 4 #include <cstring> 5 #include <cstdlib> 6 #include <iostream> 7 #include <algorithm> 8 #include <vector> 9 #include <queue> 10 #define inf 100010 11 #define INF 0x7fffffff 12 #define ll long long 13 14 namespace chiaro{ 15 16 template <class I> 17 inline void read(I &num){ 18 num = 0; char c = getchar(), up = c; 19 while(c < '0' || c > '9') up = c, c = getchar(); 20 while(c >= '0' && c <= '9') num = (num << 1) + (num << 3) + (c ^ '0'), c = getchar(); 21 up == '-' ? num = -num : 0; return; 22 } 23 template <class I> 24 inline void read(I &a, I &b) {read(a); read(b);} 25 template <class I> 26 inline void read(I &a, I &b, I &c) {read(a); read(b); read(c);} 27 28 struct Person { 29 ll dis; 30 int id; 31 }; 32 33 int n, q; 34 ll v[inf], a[inf]; 35 std::pair <ll, int> x[inf]; 36 37 inline bool cmp(Person &a, Person &b) { 38 return (a.dis == b.dis) ? (a.id < b.id) : (a.dis > b.dis); 39 } 40 41 inline void setting(){ 42 #ifndef ONLINE_JUDGE 43 freopen("C.in", "r", stdin); 44 freopen("C.out", "w", stdout); 45 #endif 46 return; 47 } 48 49 inline bool cmp (const std::pair <ll, int> &a, const std::pair <ll, int> &b) { 50 return a.first > b.first; 51 } 52 53 inline int main(){ 54 // setting(); 55 read(n); 56 for(int i = 1; i <= n; i++) read(v[i], a[i]); 57 read(q); 58 while(q--) { 59 ll t, k; read(t, k); 60 for(int i = 1; i <= n; i++) x[i] = std::make_pair(a[i] + 1ll * t * v[i], -i); 61 std::nth_element(x + 1, x + k, x + 1 + n, std::greater <std::pair <ll, int> >()); 62 printf("%lld\n", -x[k].second); 63 } 64 return 0; 65 } 66 67 } 68 69 signed main(){ return chiaro::main();}
考虑其他做法
可以发现如果将一辆车超越另一辆车称作 交换 的话,全局最多进行 $n^2$ 次的交换
那我们可以将询问按照时间为关键字排序
然后按照冒泡排序的思想来进行更新
根据上述性质,容易得到时间复杂度均摊 $O(n^2)$
1 #include <ctime> 2 #include <cmath> 3 #include <cstdio> 4 #include <cstring> 5 #include <cstdlib> 6 #include <iostream> 7 #include <algorithm> 8 #include <vector> 9 #include <queue> 10 #define inf 100010 11 #define INF 0x7fffffff 12 #define ll long long 13 14 namespace chiaro{ 15 16 template <class I> 17 inline void read(I &num){ 18 num = 0; char c = getchar(), up = c; 19 while(c < '0' || c > '9') up = c, c = getchar(); 20 while(c >= '0' && c <= '9') num = (num << 1) + (num << 3) + (c ^ '0'), c = getchar(); 21 up == '-' ? num = -num : 0; return; 22 } 23 template <class I> 24 inline void read(I &a, I &b) {read(a); read(b);} 25 template <class I> 26 inline void read(I &a, I &b, I &c) {read(a); read(b); read(c);} 27 28 struct Node { 29 ll a; 30 int b; 31 int id; 32 ll tmp; 33 }; 34 35 int n, T; 36 Node c[inf]; 37 Node q[inf]; 38 39 inline bool cmpA (const Node &a, const Node &b) {return a.a > b.a;} 40 inline bool cmpB (const Node &a, const Node &b) {return a.b > b.b;} 41 inline bool cmpID (const Node &a, const Node &b) {return a.id < b.id;} 42 43 inline void bubble(int now) { 44 for(int i = 1; i <= n; i++) { 45 for(int j = i; j > 1; --j) { 46 ll x = q[now].a * c[j].a + c[j].b; 47 ll y = q[now].a * c[j - 1].a + c[j - 1].b; 48 if(y < x) std::swap(c[j], c[j - 1]); 49 else if(x == y && c[j].id < c[j - 1].id) std::swap(c[j], c[j - 1]); 50 else break; 51 } 52 } 53 return; 54 } 55 56 inline int main(){ 57 read(n); 58 for(int i = 1; i <= n; i++) { 59 int v, a; read(v, a); 60 c[i].a = v, c[i].b = a; 61 c[i].id = i; 62 } 63 read(T); 64 for(int i = 1; i <= T; i++) { 65 int t, k; read(t, k); 66 q[i].a = t, q[i].b = k; 67 q[i].id = i; 68 } 69 std::sort(c + 1, c + 1 + n, cmpB); 70 std::sort(q + 1, q + 1 + T, cmpA); 71 for(int i = 1; i <= T; i++) { 72 bubble(i); 73 q[i].tmp = c[q[i].b].id; 74 } 75 std::sort(q + 1, q + 1 + T, cmpID); 76 for(int i = 1; i <= T; i++) printf("%lld\n", q[i].tmp); 77 return 0; 78 } 79 80 } 81 82 signed main(){ return chiaro::main();}
D. 游戏
容易想到 $O(n^2m^2)$ 暴力,考虑发掘更多性质
可以想到有性质,对于一次删除操作对应 A 串 a,和对应的 B 串 b,那么一定存在 a 或者 b 长度为 1
可以考虑证明:
$$x\times y+a\times b<(x+a)\times(y+b)$$
$$Q.E.D$$
所以可以将状态更换成 $f[0/1][i][j]$ 表示 a 还是 b 串最后一个删除的串长度为 1,同时 a 串处理到了 i 位,b 串处理到了 j 位
可以分别考虑删除两个长度为 1 和不为 1 的串串,或者删除两个长度为 1 的串串
$O(1)$ 转移
1 #include <ctime> 2 #include <cmath> 3 #include <cstdio> 4 #include <cstring> 5 #include <cstdlib> 6 #include <iostream> 7 #include <algorithm> 8 #include <vector> 9 #include <queue> 10 #define inf 2010 11 #define INF 0x7fffffff 12 #define ll long long 13 14 namespace chiaro{ 15 16 template <class I> 17 inline void read(I &num){ 18 num = 0; char c = getchar(), up = c; 19 while(c < '0' || c > '9') up = c, c = getchar(); 20 while(c >= '0' && c <= '9') num = (num << 1) + (num << 3) + (c ^ '0'), c = getchar(); 21 up == '-' ? num = -num : 0; return; 22 } 23 template <class I> 24 inline void read(I &a, I &b) {read(a); read(b);} 25 template <class I> 26 inline void read(I &a, I &b, I &c) {read(a); read(b); read(c);} 27 28 int n, m; 29 int a[inf], b[inf]; 30 ll suma[inf], sumb[inf]; 31 ll dp[2][inf][inf]; 32 33 inline int main(){ 34 read(n, m); 35 for(int i = 1; i <= n; i++) read(a[i]), --a[i]; 36 for(int i = 1; i <= m; i++) read(b[i]), --b[i]; 37 memset(dp, 0x3f, sizeof(dp)); 38 dp[0][0][0] = dp[1][0][0] = 0; 39 for(int i = 1; i <= n; i++) { 40 for(int j = 1; j <= m; j++) { 41 ll trans = 1ll * a[i] * b[j]; 42 dp[0][i][j] = std::min (dp[0][i][j - 1], std::min (dp[0][i - 1][j - 1], dp[1][i - 1][j - 1])) + trans; 43 dp[1][i][j] = std::min (dp[1][i - 1][j], std::min (dp[0][i - 1][j - 1], dp[1][i - 1][j - 1])) + trans; 44 } 45 } 46 printf("%lld\n", std::min (dp[0][n][m], dp[1][n][m])); 47 return 0; 48 } 49 50 } 51 52 signed main(){ return chiaro::main();}

浙公网安备 33010602011771号