codeforces #592 div2 ABCDEG
A. Pens and Pencils
Description
小明有一个笔盒,笔盒可以装钢笔和铅笔,钢笔写作业,铅笔考试。
每支钢笔可以写c份作业,每支铅笔可以做d份考试。
现在有a份作业,b场考试。
给定笔盒容量,问如何放笔能满足考试和作业。
Solution
签到水题
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <algorithm> 2 #include <cctype> 3 #include <cmath> 4 #include <cstdio> 5 #include <cstdlib> 6 #include <cstring> 7 #include <iostream> 8 #include <map> 9 #include <numeric> 10 #include <queue> 11 #include <set> 12 #include <stack> 13 #if __cplusplus >= 201103L 14 #include <unordered_map> 15 #include <unordered_set> 16 #endif 17 #include <vector> 18 #define lson rt << 1, l, mid 19 #define rson rt << 1 | 1, mid + 1, r 20 #define LONG_LONG_MAX 9223372036854775807LL 21 #define pblank putchar(' ') 22 #define ll LL 23 #define fastIO ios::sync_with_stdio(false), cin.tie(0), cout.tie(0) 24 using namespace std; 25 typedef long long ll; 26 typedef long double ld; 27 typedef unsigned long long ull; 28 typedef pair<int, int> P; 29 int n, m, k; 30 const int maxn = 1e5 + 10; 31 template <class T> 32 inline T read() 33 { 34 int f = 1; 35 T ret = 0; 36 char ch = getchar(); 37 while (!isdigit(ch)) 38 { 39 if (ch == '-') 40 f = -1; 41 ch = getchar(); 42 } 43 while (isdigit(ch)) 44 { 45 ret = (ret << 1) + (ret << 3) + ch - '0'; 46 ch = getchar(); 47 } 48 ret *= f; 49 return ret; 50 } 51 template <class T> 52 inline void write(T n) 53 { 54 if (n < 0) 55 { 56 putchar('-'); 57 n = -n; 58 } 59 if (n >= 10) 60 { 61 write(n / 10); 62 } 63 putchar(n % 10 + '0'); 64 } 65 template <class T> 66 inline void writeln(const T &n) 67 { 68 write(n); 69 puts(""); 70 } 71 int main(int argc, char const *argv[]) 72 { 73 #ifndef ONLINE_JUDGE 74 freopen("in.txt", "r", stdin); 75 // freopen("out.txt", "w", stdout); 76 #endif 77 int t = read<int>(); 78 while (t--) 79 { 80 int a = read<int>(), b = read<int>(), c = read<int>(), d = read<int>(); 81 k = read<int>(); 82 int x = a / c, y = b / d; 83 a % c ? ++x : 0; 84 b % d ? ++y : 0; 85 if (x + y <= k) 86 write(x), pblank, writeln(y); 87 else 88 puts("-1"); 89 } 90 return 0; 91 }
B. Rooms and Staircases
Description
小明有一栋两层楼别墅,每层有n个房间,有一些楼梯可以直通楼上楼下对应房间,没有楼梯则不能上下楼
小明可以从任意位置开始走,但他不愿意经过一间房间大于1次,
问小明最多经过多少房间
Solution
找到最左和最右的楼梯,如果没有楼梯$res=n$
否则$res=max(2(n-l+1),2r)$
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <algorithm> 2 #include <cctype> 3 #include <cmath> 4 #include <cstdio> 5 #include <cstdlib> 6 #include <cstring> 7 #include <iostream> 8 #include <map> 9 #include <numeric> 10 #include <queue> 11 #include <set> 12 #include <stack> 13 #if __cplusplus >= 201103L 14 #include <unordered_map> 15 #include <unordered_set> 16 #endif 17 #include <vector> 18 #define lson rt << 1, l, mid 19 #define rson rt << 1 | 1, mid + 1, r 20 #define LONG_LONG_MAX 9223372036854775807LL 21 #define pblank putchar(' ') 22 #define ll LL 23 #define fastIO ios::sync_with_stdio(false), cin.tie(0), cout.tie(0) 24 using namespace std; 25 typedef long long ll; 26 typedef long double ld; 27 typedef unsigned long long ull; 28 typedef pair<int, int> P; 29 int n, m, k; 30 const int maxn = 1e5 + 10; 31 template <class T> 32 inline T read() 33 { 34 int f = 1; 35 T ret = 0; 36 char ch = getchar(); 37 while (!isdigit(ch)) 38 { 39 if (ch == '-') 40 f = -1; 41 ch = getchar(); 42 } 43 while (isdigit(ch)) 44 { 45 ret = (ret << 1) + (ret << 3) + ch - '0'; 46 ch = getchar(); 47 } 48 ret *= f; 49 return ret; 50 } 51 template <class T> 52 inline void write(T n) 53 { 54 if (n < 0) 55 { 56 putchar('-'); 57 n = -n; 58 } 59 if (n >= 10) 60 { 61 write(n / 10); 62 } 63 putchar(n % 10 + '0'); 64 } 65 template <class T> 66 inline void writeln(const T &n) 67 { 68 write(n); 69 puts(""); 70 } 71 int mp[2][1010]; 72 int vis[2][1010]; 73 int cur; 74 inline int judge(int x, int y) 75 { 76 if (x >= 0 && x <= 1 && y && y <= n && !vis[x][y]) 77 return 1; 78 return 0; 79 } 80 void dfs(int x, int y) 81 { 82 vis[x][y] = 1; 83 ++cur; 84 } 85 int main(int argc, char const *argv[]) 86 { 87 #ifndef ONLINE_JUDGE 88 freopen("in.txt", "r", stdin); 89 // freopen("out.txt", "w", stdout); 90 #endif 91 int t = read<int>(); 92 while (t--) 93 { 94 n = read<int>(); 95 for (int i = 1; i <= n; i++) 96 mp[0][i] = mp[1][i] = getchar() - '0', vis[0][i] = vis[1][i] = 0; 97 getchar(); 98 int res = 0, pl = 0, pr = 0; 99 for (int i = 1; i <= n; i++) 100 if (mp[0][i] == 1) 101 pl = i; 102 for (int i = n; i >= 1; i--) 103 if (mp[0][i] == 1) 104 pr = i; 105 if (!pl) 106 res = n; 107 else 108 res = max(pl * 2, (n - pr + 1) * 2); 109 writeln(res); 110 } 111 return 0; 112 }
C. The Football Season
Description
给出$n,p,w,d,w \gt d$,求一组$x,y,z$满足$x+y+z \leq n,x*w+y*d \eq p$
Solution
看到题一眼以为是扩展欧几里得,但是自己菜没把条件罗列清楚。
赛后看题解。
假如有满足$x*w+y*d=p$存在,那么$(x+d)*w+(y-w)*d=p$依然成立
由于我们要求$x+y+z \ leq n$,那么我们可以求$x+y$最小的一组解
由上述条件可知,对于y值肯定是得小于w,因为只要$y \geq w$,我们都可以在让y减去w,并且让x上加上d,使等式成立。
且d<w,那么这样的$x+d+y-w \ lt x+y $,更优。
并且w数据范围在1e5,可以O(n)扫一遍出结果。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <algorithm> 2 #include <cctype> 3 #include <cmath> 4 #include <cstdio> 5 #include <cstdlib> 6 #include <cstring> 7 #include <iostream> 8 #include <map> 9 #include <numeric> 10 #include <queue> 11 #include <set> 12 #include <stack> 13 #if __cplusplus >= 201103L 14 #include <unordered_map> 15 #include <unordered_set> 16 #endif 17 #include <vector> 18 #define lson rt << 1, l, mid 19 #define rson rt << 1 | 1, mid + 1, r 20 #define LONG_LONG_MAX 9223372036854775807LL 21 #define pblank putchar(' ') 22 #define ll LL 23 #define fastIO ios::sync_with_stdio(false), cin.tie(0), cout.tie(0) 24 using namespace std; 25 typedef long long ll; 26 typedef long double ld; 27 typedef unsigned long long ull; 28 typedef pair<int, int> P; 29 int n, m, k; 30 const int maxn = 1e5 + 10; 31 template <class T> 32 inline T read() 33 { 34 int f = 1; 35 T ret = 0; 36 char ch = getchar(); 37 while (!isdigit(ch)) 38 { 39 if (ch == '-') 40 f = -1; 41 ch = getchar(); 42 } 43 while (isdigit(ch)) 44 { 45 ret = (ret << 1) + (ret << 3) + ch - '0'; 46 ch = getchar(); 47 } 48 ret *= f; 49 return ret; 50 } 51 template <class T> 52 inline void write(T n) 53 { 54 if (n < 0) 55 { 56 putchar('-'); 57 n = -n; 58 } 59 if (n >= 10) 60 { 61 write(n / 10); 62 } 63 putchar(n % 10 + '0'); 64 } 65 template <class T> 66 inline void writeln(const T &n) 67 { 68 write(n); 69 puts(""); 70 } 71 int main(int argc, char const *argv[]) 72 { 73 #ifndef ONLINE_JUDGE 74 freopen("in.txt", "r", stdin); 75 // freopen("out.txt", "w", stdout); 76 #endif 77 ll n = read<ll>(), p = read<ll>(), w = read<ll>(), d = read<ll>(); 78 int f = 0; 79 for (ll y = 0; y < w && !f; y++) 80 { 81 ll t = (p - y * d); 82 if (t % w) 83 continue; 84 if (t < 0) 85 break; 86 ll x = t / w; 87 if (x + y <= n) 88 { 89 write(x), pblank, write(y), pblank, writeln(n - x - y); 90 f = 1; 91 } 92 } 93 if (!f) 94 puts("-1"); 95 return 0; 96 }
D. Paint the Tree
Description
给出一棵树,每个点的可以选三种颜色之一染色,给每个点染不同颜色的价格不同。
求一种染色方案满足相邻的三个节点的颜色互异且总的染色价格最小。
Solution
显然这棵树必须是一条链才可以满足染色要求。
我们可以根据点的度判断是否为一条链。
dfs求出dfs序号,由树链剖分的知识我们可以知道相邻节点的dfs序是连续的
只要确定了前三个节点的颜色那么后续都确定了,前三种一共有6种染色,跑六次取一个最小值。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <algorithm> 2 #include <cctype> 3 #include <cmath> 4 #include <cstdio> 5 #include <cstdlib> 6 #include <cstring> 7 #include <iostream> 8 #include <map> 9 #include <numeric> 10 #include <queue> 11 #include <set> 12 #include <stack> 13 #if __cplusplus >= 201103L 14 #include <unordered_map> 15 #include <unordered_set> 16 #endif 17 #include <vector> 18 #define lson rt << 1, l, mid 19 #define rson rt << 1 | 1, mid + 1, r 20 #define LONG_LONG_MAX 9223372036854775807LL 21 #define pblank putchar(' ') 22 #define ll LL 23 #define fastIO ios::sync_with_stdio(false), cin.tie(0), cout.tie(0) 24 using namespace std; 25 typedef long long ll; 26 typedef long double ld; 27 typedef unsigned long long ull; 28 typedef pair<int, int> P; 29 int n, m, k; 30 const int maxn = 1e5 + 10; 31 template <class T> 32 inline T read() 33 { 34 int f = 1; 35 T ret = 0; 36 char ch = getchar(); 37 while (!isdigit(ch)) 38 { 39 if (ch == '-') 40 f = -1; 41 ch = getchar(); 42 } 43 while (isdigit(ch)) 44 { 45 ret = (ret << 1) + (ret << 3) + ch - '0'; 46 ch = getchar(); 47 } 48 ret *= f; 49 return ret; 50 } 51 template <class T> 52 inline void write(T n) 53 { 54 if (n < 0) 55 { 56 putchar('-'); 57 n = -n; 58 } 59 if (n >= 10) 60 { 61 write(n / 10); 62 } 63 putchar(n % 10 + '0'); 64 } 65 template <class T> 66 inline void writeln(const T &n) 67 { 68 write(n); 69 puts(""); 70 } 71 int a[maxn][4]; 72 vector<int> g[maxn]; 73 int ind[maxn], dfn[maxn], to[maxn]; 74 int tot; 75 void dfs(int x, int p) 76 { 77 dfn[x] = ++tot; 78 to[tot] = x; 79 int sz = g[x].size(); 80 for (int i = 0; i < sz; i++) 81 { 82 int y = g[x][i]; 83 if (y == p) 84 continue; 85 dfs(y, x); 86 } 87 } 88 ll cur; 89 ll ans[maxn], tmp[maxn]; 90 int main(int argc, char const *argv[]) 91 { 92 #ifndef ONLINE_JUDGE 93 freopen("in.txt", "r", stdin); 94 // freopen("out.txt", "w", stdout); 95 #endif 96 n = read<int>(); 97 for (int i = 1; i <= 3; i++) 98 for (int j = 1; j <= n; j++) 99 a[j][i] = read<int>(); 100 for (int i = 0; i < n - 1; i++) 101 { 102 int x = read<int>(), y = read<int>(); 103 g[x].emplace_back(y), g[y].emplace_back(x); 104 ++ind[y], ++ind[x]; 105 } 106 int f = 1, rt = -1; 107 for (int i = 1; i <= n && f; i++) 108 if (ind[i] > 2) 109 f = 0; 110 else if (ind[i] == 1) 111 rt = i; 112 if (!f) 113 { 114 puts("-1"); 115 return 0; 116 } 117 dfs(rt, 0); 118 ll res = 1e16; 119 int r[] = {1, 2, 3}; 120 do 121 { 122 cur = 0; 123 for (int i = 0; i < 3; i++) 124 cur += a[to[i + 1]][r[i]], tmp[i + 1] = r[i]; 125 for (int i = 4; i <= n; i++) 126 cur += a[to[i]][6 - tmp[i - 1] - tmp[i - 2]], tmp[i] = 6 - tmp[i - 1] - tmp[i - 2]; 127 if (cur < res) 128 { 129 for (int i = 1; i <= n; i++) 130 ans[to[i]] = tmp[i]; 131 res = cur; 132 } 133 } while (next_permutation(r, r + 3)); 134 writeln(res); 135 for (int i = 1; i <= n; i++) 136 write(ans[i]), pblank; 137 return 0; 138 }
E. Minimizing Difference
给出一个长为n的序列和k次操作。
每次操作可以将序列里的一个值加一或者减一。
问最多k次操作后,求序列里的最小的最大最小值之差。
Solution
贪心乱搞。
记录一个当前最小值和当前最大值,以及对应出现的次数。
哪个的次数少就先搞哪个。
对于加一,二分找出原序列里大于最小值的第一个点,判断当前剩余次数能否加到下一个点,更新最小值和记录次数的哈希表。
减一同上,减一的二分查找可以先整一个原序列的相反数序列。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <algorithm> 2 #include <cctype> 3 #include <cmath> 4 #include <cstdio> 5 #include <cstdlib> 6 #include <cstring> 7 #include <fstream> 8 #include <iostream> 9 #include <map> 10 #include <numeric> 11 #include <queue> 12 #include <set> 13 #include <stack> 14 #if __cplusplus >= 201103L 15 #include <unordered_map> 16 #include <unordered_set> 17 #endif 18 #include <vector> 19 #define lson rt << 1, l, mid 20 #define rson rt << 1 | 1, mid + 1, r 21 #define LONG_LONG_MAX 9223372036854775807LL 22 #define pblank putchar(' ') 23 #define ll LL 24 #define fastIO ios::sync_with_stdio(false), cin.tie(0), cout.tie(0) 25 using namespace std; 26 typedef long long ll; 27 typedef long double ld; 28 typedef unsigned long long ull; 29 typedef pair<int, int> P; 30 int n, m, k; 31 const int maxn = 1e5 + 10; 32 template <class T> 33 inline T read() 34 { 35 int f = 1; 36 T ret = 0; 37 char ch = getchar(); 38 while (!isdigit(ch)) 39 { 40 if (ch == '-') 41 f = -1; 42 ch = getchar(); 43 } 44 while (isdigit(ch)) 45 { 46 ret = (ret << 1) + (ret << 3) + ch - '0'; 47 ch = getchar(); 48 } 49 ret *= f; 50 return ret; 51 } 52 template <class T> 53 inline void write(T n) 54 { 55 if (n < 0) 56 { 57 putchar('-'); 58 n = -n; 59 } 60 if (n >= 10) 61 { 62 write(n / 10); 63 } 64 putchar(n % 10 + '0'); 65 } 66 template <class T> 67 inline void writeln(const T &n) 68 { 69 write(n); 70 puts(""); 71 } 72 unordered_map<ll, int> mp; 73 vector<ll> a, b; 74 int main(int argc, char const *argv[]) 75 { 76 #ifndef ONLINE_JUDGE 77 freopen("in.txt", "r", stdin); 78 // freopen("out.txt", "w", stdout); 79 #endif 80 n = read<int>(); 81 ll q = read<ll>(); 82 for (int i = 1; i <= n; i++) 83 { 84 ll x = read<ll>(); 85 ++mp[x]; 86 a.emplace_back(x); 87 b.emplace_back(-x); 88 } 89 sort(a.begin(), a.end()); 90 sort(b.begin(), b.end()); 91 auto aend = unique(a.begin(), a.end()); 92 auto bend = unique(b.begin(), b.end()); 93 ll minx = a.front(), maxx = a.back(); 94 while (q) 95 { 96 if (minx == maxx) 97 break; 98 int lminx = mp[minx]; 99 int lmaxx = mp[maxx]; 100 if (lminx < lmaxx) 101 { 102 auto pos = upper_bound(a.begin(), aend, minx); 103 ll dec = *pos - minx; 104 if (dec * lminx <= q) 105 { 106 q -= dec * lminx; 107 mp[*pos] += lminx; 108 mp.erase(minx); 109 minx = *pos; 110 } 111 else 112 { 113 ll times = q / lminx; 114 mp.erase(minx); 115 minx += times; 116 q = 0; 117 } 118 } 119 else 120 { 121 auto pos = upper_bound(b.begin(), bend, -maxx); 122 ll dec = maxx + *pos; 123 if (dec * lmaxx <= q) 124 { 125 q -= dec * lmaxx; 126 mp[-*pos] += lmaxx; 127 mp.erase(maxx); 128 maxx = -*pos; 129 } 130 else 131 { 132 ll times = q / lmaxx; 133 mp.erase(maxx); 134 maxx -= times; 135 q = 0; 136 } 137 } 138 } 139 writeln(maxx - minx); 140 return 0; 141 }
G. Running in Pairs
Description
给出两个1..n的排列,每个排列可以任意交换两个位置。
求$\sum_1^n max(a[i],b[i]) \leq k $的最大值
Solution
思路源自题解
首先对于序列里的某一个值最多只会对答案有两次贡献。
第一个和最后一个交换可以获得n-1的新贡献,
而此时再考虑第一或最后和其他值的交换不会有新贡献
那么我们就移动指针。
判断第二个和倒二,tmp=n-1-2
。。。
当此时的累计值加上当前的tmp值大于了k,就找一个最优的右值使之满足r-l+cur<=k
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <algorithm> 2 #include <cctype> 3 #include <cmath> 4 #include <cstdio> 5 #include <cstdlib> 6 #include <cstring> 7 #include <iostream> 8 #include <map> 9 #include <numeric> 10 #include <queue> 11 #include <set> 12 #include <stack> 13 #if __cplusplus >= 201103L 14 #include <unordered_map> 15 #include <unordered_set> 16 #endif 17 #include <vector> 18 #define lson rt << 1, l, mid 19 #define rson rt << 1 | 1, mid + 1, r 20 #define LONG_LONG_MAX 9223372036854775807LL 21 #define pblank putchar(' ') 22 #define ll LL 23 #define fastIO ios::sync_with_stdio(false), cin.tie(0), cout.tie(0) 24 using namespace std; 25 typedef long long ll; 26 typedef long double ld; 27 typedef unsigned long long ull; 28 typedef pair<int, int> P; 29 int n, m, k; 30 const int maxn = 1e6 + 10; 31 template <class T> 32 inline T read() 33 { 34 int f = 1; 35 T ret = 0; 36 char ch = getchar(); 37 while (!isdigit(ch)) 38 { 39 if (ch == '-') 40 f = -1; 41 ch = getchar(); 42 } 43 while (isdigit(ch)) 44 { 45 ret = (ret << 1) + (ret << 3) + ch - '0'; 46 ch = getchar(); 47 } 48 ret *= f; 49 return ret; 50 } 51 template <class T> 52 inline void write(T n) 53 { 54 if (n < 0) 55 { 56 putchar('-'); 57 n = -n; 58 } 59 if (n >= 10) 60 { 61 write(n / 10); 62 } 63 putchar(n % 10 + '0'); 64 } 65 template <class T> 66 inline void writeln(const T &n) 67 { 68 write(n); 69 puts(""); 70 } 71 ll t[maxn]; 72 int main(int argc, char const *argv[]) 73 { 74 #ifndef ONLINE_JUDGE 75 freopen("in.txt", "r", stdin); 76 // freopen("out.txt", "w", stdout); 77 #endif 78 n = read<int>(); 79 ll k = read<ll>(); 80 for (int i = 1; i <= n; i++) 81 t[i] = i; 82 ll cur = (1LL + n) * n / 2; 83 if (k < cur) 84 { 85 puts("-1"); 86 return 0; 87 } 88 else 89 { 90 int l = 1, r = n; 91 while (l < r) 92 { 93 int temp = r - l; 94 if (cur + temp <= k) 95 { 96 cur += temp; 97 swap(t[l], t[r]); 98 ++l, --r; 99 } 100 else 101 { 102 int tmp = k - cur + l; 103 swap(t[tmp], t[l]); 104 cur += tmp - l; 105 break; 106 } 107 } 108 } 109 writeln(cur); 110 for (int i = 1; i <= n; i++) 111 write(i), pblank; 112 puts(""); 113 for (int i = 1; i <= n; i++) 114 write(t[i]), pblank; 115 116 return 0; 117 }