牛客国庆集训派对Day1 Solution
A Tobaku Mokushiroku Kaiji
水。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int a[3], b[3]; 5 6 void Run() 7 { 8 while (scanf("%d", a) != EOF) 9 { 10 for (int i = 1; i < 3; ++i) scanf("%d", a + i); 11 for (int i = 0; i < 3; ++i) scanf("%d", b + i); 12 printf("%d\n", min(a[0], b[1]) + min(a[1], b[2]) + min(a[2], b[0])); 13 } 14 } 15 16 int main() 17 { 18 #ifdef LOCAL 19 freopen("Test.in", "r", stdin); 20 #endif 21 22 Run(); 23 return 0; 24 }
B Attack on Titan
留坑。
C Utawarerumono
思路:好像暴力就能过。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <bits/stdc++.h> 2 using namespace std; 3 using ll = long long; 4 5 ll a, b, c, p1, p2, q1, q2; 6 7 int main() 8 { 9 while (scanf("%lld%lld%lld", &a, &b, &c) != EOF) 10 { 11 scanf("%lld%lld", &p1, &p2); 12 scanf("%lld%lld", &q1, &q2); 13 ll res = 0x3f3f3f3f3f3f3f3f; 14 for (ll x = -100000; x <= 100000; ++x) 15 { 16 if ((c - a * x) % b) continue; 17 ll y = (c - a * x) / b; 18 res = min(res, p2 * x * x + p1 * x + q2 * y * y + q1 * y); 19 } 20 if (res == 0x3f3f3f3f3f3f3f3f) 21 { 22 puts("Kuon"); 23 continue; 24 } 25 printf("%lld\n", res); 26 } 27 return 0; 28 }
D Love Live!
思路:将边按权值从小到大排序,一条一条往里加,每加入一条边要合并两个联通块,用并查集维护,然后开n棵trie树维护异或最大,简单路径上的异或和可以理解为两个点到根节点的前缀异或再异或,合并的时候启发式合并,查询的时候一定要经过那条边,那就是用一个联通块里的元素查找在另一个联通块对应的trie树里面查找,启发式查找
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define N 100010 5 6 struct Edge 7 { 8 int u, v, nx, w; 9 Edge() {} 10 Edge(int u, int v, int nx, int w) : u(u), v(v), nx(nx), w(w) {} 11 Edge(int u, int v, int w) : u(u), v(v), w(w) {} 12 bool operator < (const Edge &r) const 13 { 14 return w < r.w; 15 } 16 }edge[N << 1], G[N]; 17 18 int n; 19 int head[N], pos; 20 int prefix[N], fa[N], sz[N]; 21 vector <int> v[N]; 22 23 void addedge(int u, int v, int w) 24 { 25 edge[++pos] = Edge(u, v, head[u], w); head[u] = pos; 26 } 27 28 void DFS(int u, int fa) 29 { 30 for (int it = head[u]; ~it; it = edge[it].nx) 31 { 32 int v = edge[it].v; 33 if (v == fa) continue; 34 prefix[v] = prefix[u] ^ edge[it].w; 35 DFS(v, u); 36 } 37 } 38 39 struct TRIE 40 { 41 int cnt; 42 int T[N]; 43 struct node 44 { 45 int son[2]; 46 node() 47 { 48 memset(son, 0, sizeof son); 49 } 50 }a[N * 400]; 51 52 void Init() 53 { 54 cnt = n + 1; 55 } 56 57 void Insert(int root, int x) 58 { 59 bitset <20> b; b = x; 60 for (int i = 19; i >= 0; --i) 61 { 62 if (!a[root].son[b[i]]) 63 a[root].son[b[i]] = ++cnt; 64 root = a[root].son[b[i]]; 65 } 66 } 67 68 int query(int root, int x) 69 { 70 bitset <20> b; b = x; 71 int res = 0; 72 for (int i = 19; i >= 0; --i) 73 { 74 int id = b[i] ^ 1; 75 bool flag = true; 76 if (!a[root].son[id]) 77 { 78 flag = false; 79 id ^= 1; 80 } 81 if (flag) res += 1 << i; 82 root = a[root].son[id]; 83 } 84 return res; 85 } 86 }trie; 87 88 int find(int x) 89 { 90 if (x != fa[x]) 91 fa[x] = find(fa[x]); 92 return fa[x]; 93 } 94 95 void Init() 96 { 97 memset(head, -1, sizeof head); pos = 0; 98 prefix[1] = 0; 99 trie.Init(); 100 } 101 102 void Run() 103 { 104 while (scanf("%d", &n) != EOF) 105 { 106 Init(); 107 for (int i = 1, u, v, w; i < n; ++i) 108 { 109 scanf("%d%d%d", &u, &v, &w); 110 addedge(u, v, w); 111 addedge(v, u, w); 112 G[i] = Edge(u, v, w); 113 } 114 DFS(1, 1); 115 for (int i = 1; i <= n; ++i) 116 { 117 fa[i] = i; 118 sz[i] = 1; 119 trie.T[i] = i; 120 trie.Insert(trie.T[i], prefix[i]); 121 v[i].push_back(prefix[i]); 122 } 123 sort(G + 1, G + n); 124 for (int i = 1; i < n; ++i) 125 { 126 int x = G[i].u, y = G[i].v; 127 int fx = find(x), fy = find(y); 128 if (sz[fx] > sz[fy]) swap(x, y), swap(fx, fy); 129 int res = 0; 130 for (auto it : v[fx]) 131 { 132 res = max(res, trie.query(trie.T[fy], it)); 133 } 134 for (auto it : v[fx]) 135 { 136 trie.Insert(trie.T[fy], it); 137 v[fy].push_back(it); 138 } 139 printf("%d%c", res, " \n"[i == n - 1]); 140 fa[fx] = fy; 141 sz[fy] += sz[fx]; 142 } 143 } 144 } 145 146 int main() 147 { 148 #ifdef LOCAL 149 freopen("Test.in", "r", stdin); 150 #endif 151 152 Run(); 153 return 0; 154 }
E Eustia of the Tarnished Wings
思路:排序,然后贪心合并即可
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define N 1000010 5 6 int n, m; 7 int arr[N]; 8 9 void Run() 10 { 11 while (scanf("%d%d", &n, &m) != EOF) 12 { 13 for (int i = 1; i <= n; ++i) scanf("%d", arr + i); 14 sort(arr + 1, arr + 1 + n); 15 int res = 1; 16 for (int i = 2; i <= n; ++i) if (arr[i] - arr[i - 1] > m) 17 ++res; 18 printf("%d\n", res); 19 } 20 } 21 22 int main() 23 { 24 #ifdef LOCAL 25 freopen("Test.in", "r", stdin); 26 #endif 27 28 Run(); 29 return 0; 30 }
F Baldr Sky
留坑。
G Kimi to Kanojo to Kanojo no Koi
留坑。
H One Piece
留坑。
I Steins;Gate
留坑。
J Princess Principal
思路:用栈维护括号序列
其实假设存在合法文档 那么每一个括号都有一个唯一的对应括号
比如说 (()) 肯定是中间两个匹配,再外面两个匹配
那么我们直接用栈维护一下,找到每个左括号的右匹配,以及找到每个有括号的左匹配,然后RMQ倍增维护最括号的最大右匹配,右括号的最小左匹配,如果最大值超过r 或者 最小值小于l 那么是不合法的
还有一种情况 就是 ([) 那么这三个括号都是不合法的
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define N 1000010 5 #define INF 0x3f3f3f3f 6 7 int n, m, q; 8 int arr[N], L[N], R[N]; 9 int mm[N]; 10 stack <int> sta; 11 12 void Init() 13 { 14 mm[0] = -1; 15 for (int i = 1; i <= n; ++i) 16 mm[i] = ((i & (i - 1)) == 0) ? mm[i - 1] + 1 : mm[i - 1]; 17 } 18 19 struct RMQ 20 { 21 int dp[N][20]; // 1 max 0 min 22 void Init(int n, int b[], int vis) 23 { 24 for (int i = 1; i <= n; ++i) 25 dp[i][0] = b[i]; 26 for (int j = 1; j <= mm[n]; ++j) 27 for (int i = 1; i + (1 << j) - 1 <= n; ++i) 28 { 29 if (vis) 30 dp[i][j] = max(dp[i][j - 1], dp[i + (1 << (j - 1))][j - 1]); 31 else 32 dp[i][j] = min(dp[i][j - 1], dp[i + (1 << (j - 1))][j - 1]); 33 } 34 } 35 36 int query(int x, int y, int vis) 37 { 38 int k = mm[y - x + 1]; 39 if (vis) 40 return max(dp[x][k], dp[y - (1 << k) + 1][k]); 41 else 42 return min(dp[x][k], dp[y - (1 << k) + 1][k]); 43 } 44 }rmq[2]; 45 46 bool ok(int x, int y) 47 { 48 if (rmq[0].query(x, y, 0) < x) return false; 49 if (rmq[1].query(x, y, 1) > y) return false; 50 return true; 51 } 52 53 void Run() 54 { 55 while (scanf("%d%d%d", &n, &m, &q) != EOF) 56 { 57 memset(L, -1, sizeof L); 58 memset(R, 0x3f, sizeof R); 59 for (int i = 1; i <= n; ++i) scanf("%d", arr + i); 60 for (int i = 1; i <= n; ++i) 61 { 62 if (arr[i] & 1) 63 { 64 if (!sta.empty()) 65 { 66 int top = sta.top(); sta.pop(); 67 if (arr[i] / 2 == arr[top] / 2) L[i] = top; 68 } 69 } 70 else 71 sta.push(i); 72 } 73 while (!sta.empty()) sta.pop(); 74 for (int i = n; i >= 1; --i) 75 { 76 if (arr[i] % 2 == 0) 77 { 78 if (!sta.empty()) 79 { 80 int top = sta.top(); sta.pop(); 81 if (arr[i] / 2 == arr[top] / 2) R[i] = top; 82 } 83 } 84 else 85 sta.push(i); 86 } 87 for (int i = 1; i <= n; ++i) 88 { 89 if (arr[i] & 1) R[i] = -1; 90 else L[i] = INF; 91 } 92 Init(); 93 rmq[0].Init(n, L, 0); 94 rmq[1].Init(n, R, 1); 95 for (int i = 1, x, y; i <= q; ++i) 96 { 97 scanf("%d%d", &x, &y); 98 puts(ok(x, y) ? "Yes" : "No"); 99 } 100 } 101 } 102 103 int main() 104 { 105 #ifdef LOCAL 106 freopen("Test.in", "r", stdin); 107 #endif 108 109 Run(); 110 return 0; 111 }
K Tengen Toppa Gurren Lagann
留坑。
L New Game!
思路:分别处理 直线到圆的最短距离,圆到圆的最短距离,直线到直线的最短距离,然后跑最短路即可
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define N 1010 5 #define INF 0x3f3f3f3f 6 7 const double eps = 1e-8; 8 9 int sgn(double x) 10 { 11 if (fabs(x) < eps) return 0; 12 if (x < 0) return -1; 13 else return 1; 14 } 15 16 struct Point 17 { 18 double x, y; 19 Point() {} 20 Point(double _x, double _y) 21 { 22 x = _x; y = _y; 23 } 24 double operator ^(const Point &b) const { return x * b.y - y * b.x; } 25 double distance(Point p) { return hypot(x - p.x, y - p.y); } 26 Point operator - (const Point &b) const { return Point(x - b.x, y - b.y); } 27 }; 28 29 struct Line 30 { 31 Point s, e; 32 Line() {} 33 Line(double a, double b, double c) 34 { 35 if (sgn(a) == 0) 36 { 37 s = Point(0, -c / b); 38 e = Point(1, -c / b); 39 } 40 else if (sgn(b) == 0) 41 { 42 s = Point(-c / a, 0); 43 e = Point(-c / a, 1); 44 } 45 else 46 { 47 s = Point(0, -c / b); 48 e = Point(1, (-c - a) / b); 49 } 50 } 51 double length() { return s.distance(e); } 52 double dispointtoline(Point p) { return fabs((p - s) ^ (e - s)) / length(); } 53 }L[2]; 54 55 struct circle 56 { 57 Point p; 58 double r; 59 circle() {} 60 circle(double x, double y, double _r) 61 { 62 p = Point(x, y); 63 r = _r; 64 } 65 }arr[N]; 66 67 68 int n, A, B, C1, C2; 69 double x, y, r; 70 double G[N][N]; 71 72 void work0(int x, int y) 73 { 74 double dis = arr[x].p.distance(arr[y].p); 75 G[x][y] = max(0.0, dis - arr[x].r - arr[y].r); 76 G[y][x] = G[x][y]; 77 } 78 79 void work1(int x, int y) 80 { 81 double dis = L[x].dispointtoline(arr[y].p); 82 G[x][y] = max(0.0, dis - arr[y].r); 83 G[y][x] = G[x][y]; 84 } 85 86 double dis[N]; 87 bool used[N]; 88 89 void Dijkstra () 90 { 91 for (int i = 0; i <= n + 1; ++i) dis[i] = INF * 1.0, used[i] = false; 92 dis[0] = 0; 93 for (int j = 0; j <= n + 1; ++j) 94 { 95 int k = -1; 96 double Min = INF * 1.0; 97 for (int i = 0; i <= n + 1; ++i) 98 { 99 if (!used[i] && dis[i] < Min) 100 { 101 Min = dis[i]; 102 k = i; 103 } 104 } 105 used[k] = 1; 106 for (int i = 0; i <= n + 1; ++i) 107 if (!used[i] && dis[k] + G[k][i] < dis[i]) 108 dis[i] = dis[k] + G[k][i]; 109 } 110 } 111 112 void Run() 113 { 114 while (scanf("%d%d%d%d%d", &n, &A, &B, &C1, &C2) != EOF) 115 { 116 memset(G, 0x3f, sizeof G); 117 L[0] = Line(A, B, C1); 118 L[1] = Line(A, B, C2); 119 for (int i = 2; i <= n + 1; ++i) 120 { 121 scanf("%lf%lf%lf", &x, &y, &r); 122 arr[i] = circle(x, y, r); 123 G[i][i] = 0; 124 } 125 for (int i = 2; i <= n + 1; ++i) 126 for (int j = i + 1; j <= n + 1; ++j) 127 work0(i, j); 128 for (int i = 0; i < 2; ++i) 129 for (int j = 2; j <= n + 1; ++j) 130 work1(i, j); 131 G[0][1] = abs(C1 - C2) / sqrt(A * A + B * B); 132 G[1][0] = G[0][1]; 133 Dijkstra(); 134 printf("%.10f\n", dis[1]); 135 } 136 } 137 138 int main() 139 { 140 Run(); 141 return 0; 142 }