2018 Multi-University Training Contest 5 Solution
A - Always Online
Unsolved.
B - Beautiful Now
Solved.
题意:
给出一个n, k 每次可以将n这个数字上的某两位交换,最多交换k次,求交换后的最大和最小值
思路:
很明显有一种思路,对于最小值,尽可能把小的放前面, 对于最大值,尽可能把打的放前面。但是如果有多个最小数字或者最大数字会无法得出放哪个好,因此BFS一下即可
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 const int INF = 0x3f3f3f3f; 6 const int maxn = 1e5 + 10; 7 8 struct node{ 9 int num, idx, step; 10 node(){} 11 node(int num, int idx, int step) :num(num), idx(idx), step(step){} 12 }; 13 14 int n, k; 15 int cnt; 16 int arr[maxn]; 17 18 int BFS1() 19 { 20 queue<node>q; 21 q.push(node(n, cnt, 0)); 22 int ans = INF; 23 while(!q.empty()) 24 { 25 node now = q.front(); 26 q.pop(); 27 ans = min(ans, now.num); 28 if(now.step == k) continue; 29 if(now.idx == 1) continue; 30 int tmp = now.num; 31 cnt = 0; 32 while(tmp) 33 { 34 arr[++cnt] = tmp % 10; 35 tmp /= 10; 36 } 37 int Min = now.idx; 38 for(int i = now.idx - 1; i >= 1; --i) 39 { 40 if(arr[i] == arr[now.idx]) continue; 41 if(arr[i] == 0 && now.idx == cnt) continue; 42 if(arr[i] < arr[Min]) Min = i; 43 } 44 if(Min == now.idx) 45 { 46 q.push(node(now.num, now.idx - 1, now.step)); 47 } 48 else 49 { 50 for(int i = now.idx - 1; i >= 1; --i) 51 { 52 if(arr[i] == arr[Min]) 53 { 54 swap(arr[i], arr[now.idx]); 55 tmp = 0; 56 for(int j = cnt; j >= 1; --j) 57 { 58 tmp = tmp * 10 + arr[j]; 59 } 60 q.push(node(tmp, now.idx - 1, now.step + 1)); 61 swap(arr[i], arr[now.idx]); 62 } 63 } 64 } 65 } 66 return ans; 67 } 68 69 int BFS2() 70 { 71 queue<node>q; 72 q.push(node(n, cnt, 0)); 73 int ans = -INF; 74 while(!q.empty()) 75 { 76 node now = q.front(); 77 q.pop(); 78 ans = max(ans, now.num); 79 if(now.step == k) continue; 80 if(now.idx == 1) continue; 81 int tmp = now.num; 82 cnt = 0; 83 while(tmp) 84 { 85 arr[++cnt] = tmp % 10; 86 tmp /= 10; 87 } 88 int Max = now.idx; 89 for(int i = now.idx - 1; i >= 1; --i) 90 { 91 if(arr[i] == arr[now.idx]) continue; 92 if(arr[i] > arr[Max]) Max = i; 93 } 94 if(Max == now.idx) 95 { 96 q.push(node(now.num, now.idx - 1, now.step)); 97 } 98 else 99 { 100 for(int i = now.idx - 1; i >= 1; --i) 101 { 102 if(arr[i] == arr[Max]) 103 { 104 swap(arr[i], arr[now.idx]); 105 tmp = 0; 106 for(int j = cnt; j >= 1; --j) 107 { 108 tmp = tmp * 10 + arr[j]; 109 } 110 q.push(node(tmp, now.idx - 1, now.step + 1)); 111 swap(arr[i], arr[now.idx]); 112 } 113 } 114 } 115 } 116 return ans; 117 } 118 119 int main() 120 { 121 int t; 122 scanf("%d", &t); 123 while(t--) 124 { 125 scanf("%d %d", &n ,&k); 126 int tmp = n; 127 cnt = 0; 128 while(tmp) 129 { 130 cnt++; 131 tmp /= 10; 132 } 133 k = min(k, cnt - 1); 134 int ans1 = BFS1(); 135 int ans2 = BFS2(); 136 printf("%d %d\n", ans1, ans2); 137 } 138 return 0; 139 }
C - Call It What You Want
Unsolved.
D - Daylight
Unsolved.
E - Everything Has Changed
Solved.
题意:
求多个圆的周长并
思路:
对于不想交和内含的直接continue,相切的直接相加。对于相交的可以减去大圆上的弧长,加上小圆的弧长
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 const double PI = acos(-1.0); 6 const double eps = 1e-8; 7 8 int sgn(double x) 9 { 10 if(fabs(x) < eps) return 0; 11 else return x > 0 ? 1 : -1; 12 } 13 14 struct Point{ 15 double x, y; 16 Point(){} 17 Point(double _x, double _y) 18 { 19 x = _x; 20 y = _y; 21 } 22 23 double distance(Point p) 24 { 25 return hypot(x - p.x, y - p.y); 26 } 27 }P; 28 29 int n; 30 double R, r; 31 32 int main() 33 { 34 int t; 35 scanf("%d", &t); 36 while(t--) 37 { 38 scanf("%d %lf", &n, &R); 39 double ans = 2 * R * PI; 40 for(int i = 1; i <= n; ++i) 41 { 42 scanf("%lf %lf %lf", &P.x, &P.y, &r); 43 double dis = P.distance(Point(0.0, 0.0)); 44 if(sgn(dis - (r + R)) >= 0) continue; 45 else if(sgn(dis - (R - r)) < 0) continue; 46 else if(sgn(dis - (R - r)) == 0) 47 { 48 ans += 2 * PI * r; 49 continue; 50 } 51 double arc1 = (R * R + dis * dis - r * r) / (2.0 * R * dis); 52 arc1 = 2 * acos(arc1); 53 double arc2 = (r * r + dis * dis - R * R) / (2.0 * r * dis); 54 arc2 = 2 * acos(arc2); 55 ans -= R * arc1; 56 ans += r * arc2; 57 } 58 printf("%.10f\n", ans); 59 } 60 return 0; 61 }
F - Fireflies
Unsolved.
G - Glad You Came
Upsolved.
题意:
m个区间操作,每次给$[L, R]区间内小于v 的数变为v$
思路:
线段树,维护最大最小值+剪枝,因为数据随机才可以这样做。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define N 5000010 5 #define M 100010 6 #define ui unsigned int 7 #define ll long long 8 int t, n, m; 9 ui x, y, z, w; 10 ui f[N << 2]; 11 ui MOD = (ui)1 << 30; 12 13 ui rng61() 14 { 15 x = x ^ (x << 11); 16 x = x ^ (x >> 4); 17 x = x ^ (x << 5); 18 x = x ^ (x >> 14); 19 w = x ^ y ^ z; 20 x = y; 21 y = z; 22 z = w; 23 return z; 24 } 25 26 struct SEG 27 { 28 ui lazy[M << 2], Max[M << 2], Min[M << 2]; 29 void Init() 30 { 31 memset(lazy, 0, sizeof lazy); 32 memset(Max, 0, sizeof Max); 33 memset(Min, 0, sizeof Min); 34 } 35 void pushup(int id) 36 { 37 Max[id] = max(Max[id << 1], Max[id << 1 | 1]); 38 Min[id] = min(Min[id << 1], Min[id << 1 | 1]); 39 } 40 void pushdown(int id) 41 { 42 if (!lazy[id]) return; 43 lazy[id << 1] = lazy[id]; 44 Max[id << 1] = lazy[id]; 45 Min[id << 1] = lazy[id]; 46 lazy[id << 1 | 1] = lazy[id]; 47 Max[id << 1 | 1] = lazy[id]; 48 Min[id << 1 | 1] = lazy[id]; 49 lazy[id] = 0; 50 } 51 void update(int id, int l, int r, int ql, int qr, ui val) 52 { 53 if (Min[id] >= val) return; 54 if (l >= ql && r <= qr && Max[id] < val) 55 { 56 lazy[id] = Max[id] = val; 57 return; 58 } 59 pushdown(id); 60 int mid = (l + r) >> 1; 61 if (ql <= mid) update(id << 1, l, mid, ql, qr, val); 62 if (qr > mid) update(id << 1 | 1, mid + 1, r, ql, qr, val); 63 pushup(id); 64 } 65 int query(int id, int l, int r, int pos) 66 { 67 if (l == r) return Max[id]; 68 pushdown(id); 69 int mid = (l + r) >> 1; 70 if (pos <= mid) return query(id << 1, l, mid, pos); 71 else return query(id << 1 | 1, mid + 1, r, pos); 72 } 73 }seg; 74 75 int main() 76 { 77 scanf("%d", &t); 78 while (t--) 79 { 80 scanf("%d%d%u%u%u", &n, &m, &x, &y, &z); 81 for (int i = 1; i <= 3 * m; ++i) f[i] = rng61(); 82 seg.Init(); 83 for (int i = 1, l, r, v; i <= m; ++i) 84 { 85 l = f[3 * i - 2] % n + 1; 86 r = f[3 * i - 1] % n + 1; 87 v = f[3 * i] % MOD; 88 if (l > r) swap(l, r); 89 seg.update(1, 1, n, l, r, v); 90 } 91 ll res = 0; 92 for (int i = 1; i <= n; ++i) 93 res ^= (ll)seg.query(1, 1, n, i) * (ll)i; 94 printf("%lld\n", res); 95 } 96 return 0; 97 }
H - Hills And Valleys
Upsolved,
题意:
给出一个长为n的数字串,每一位范围是$[0, 9]$,可以翻转其中一段,使得最长非下降子序列最长
思路:
也就是说 可以存在这样一段
$0, 1, 2....., x, (x - 1) , y, (y - 1).... x, y + 1, y + 2..$
我们知道,如果不可以翻转,求最长上升子序列的话,我们可以将原串 和模式串$0123456789$ 求最长公共子序列
那么翻转的话,我们通过枚举翻转的区间$C(2, 10)$ 构造出上述的模式串,再求最长公共子序列
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define N 100010 5 #define INF 0x3f3f3f3f 6 int t, n, m, a[N], b[20]; 7 int dp[N][20], tl[N][20], tr[N][20], res, l, r, ql, qr; 8 9 void solve() 10 { 11 for (int i = 1; i <= m; ++i) dp[0][i] = 0, tl[0][i] = -1, tr[0][i] = -1; 12 for (int i = 1; i <= n; ++i) for (int j = 1; j <= m; ++j) 13 { 14 dp[i][j] = dp[i - 1][j]; 15 tl[i][j] = tl[i - 1][j]; 16 tr[i][j] = tr[i - 1][j]; 17 if (a[i] == b[j]) 18 { 19 ++dp[i][j]; 20 if (j == ql && tl[i][j] == -1) tl[i][j] = i; 21 if (j == qr) tr[i][j] = i; 22 } 23 if (j > 1 && dp[i][j - 1] > dp[i][j]) 24 { 25 dp[i][j] = dp[i][j - 1]; 26 tl[i][j] = tl[i][j - 1]; 27 tr[i][j] = tr[i][j - 1]; 28 } 29 } 30 if (ql == 1 && qr == 1) 31 { 32 res = dp[n][m]; 33 l = 1; 34 r = 1; 35 } 36 else if (dp[n][m] > res && tl[n][m] != -1 && tr[n][m] != -1) 37 { 38 res = dp[n][m]; 39 l = tl[n][m]; 40 r = tr[n][m]; 41 } 42 } 43 44 int main() 45 { 46 scanf("%d", &t); 47 while (t--) 48 { 49 scanf("%d", &n); 50 res = 1, l = 1, r = 1; 51 for (int i = 1; i <= n; ++i) scanf("%1d", a + i); 52 for (int i = 1; i <= 10; ++i) b[i] = i - 1; m = 10; ql = 1, qr = 1; 53 solve(); 54 for (int i = 1; i < m; ++i) for (int j = i + 1; j <= 10; ++j) 55 { 56 m = 0; 57 for (int pos = 1; pos <= i; ++pos) b[++m] = pos - 1; 58 ql = m + 1; 59 for (int pos = j; pos >= i; --pos) b[++m] = pos - 1; 60 qr = m; 61 for (int pos = j; pos <= 10; ++pos) b[++m] = pos - 1; 62 solve(); 63 //for (int i = 1; i <= m; ++i) printf("%d%c", b[i], " \n"[i == m]); 64 } 65 printf("%d %d %d\n", res, l, r); 66 } 67 return 0; 68 }
I - Innocence
Unsolved.
J - Just So You Know
Unsolved.
K - Kaleidoscope
Unsolved.
L - Lost In The Echo
Unsolved.