USACO 2018 US Open Contest, Gold 总结
这套USACO还是比较简单的把。。。
P1 Out of Sorts
一看伪代码就是鸡尾酒排序,但是与这个没关系
离散+排序后我们能够发现结论:
对于每个𝑖
1.向后扫会保证把前 𝑖 个位置上一个值> 𝑖 的数扔到后边去
2.向前扫会保证被换到前𝑖 个位置上的新数的值是≤ 𝑖 的
于是扫一遍就行了
1 //usaco 2018 open gold 2 #include <map> 3 #include <set> 4 #include <cmath> 5 #include <ctime> 6 #include <queue> 7 #include <stack> 8 #include <vector> 9 #include <bitset> 10 #include <cstdio> 11 #include <cctype> 12 #include <string> 13 #include <cstring> 14 #include <cassert> 15 #include <climits> 16 #include <cstdlib> 17 #include <iostream> 18 #include <algorithm> 19 #include <functional> 20 using namespace std ; 21 22 #define rep(i, a, b) for (int (i) = (a); (i) <= (b); (i)++) 23 #define Rep(i, a, b) for (int (i) = (a) - 1; (i) < (b); (i)++) 24 #define REP(i, a, b) for (int (i) = (a); (i) >= (b); (i)--) 25 #define clr(a) memset(a, 0, sizeof(a)) 26 #define Sort(a, len, cmp) sort(a + 1, a + len + 1, cmp) 27 #define ass(a, sum) memset(a, sum, sizeof(a)) 28 29 #define ls ((rt) << 1) 30 #define rs ((rt) << 1 | 1) 31 #define lowbit(x) (x & -x) 32 #define mp make_pair 33 #define pb push_back 34 #define fi first 35 #define se second 36 #define endl '\n' 37 #define ENDL cout << endl 38 #define SZ(x) ((int)x.size()) 39 40 typedef long long ll ; 41 typedef unsigned long long ull ; 42 typedef vector <int> Vi ; 43 typedef pair <int, int> Pii ; 44 typedef pair <ll, ll> Pll ; 45 typedef map <int, int> mii ; 46 typedef map <string, int> msi ; 47 typedef map <ll, ll> mll ; 48 49 const int N = 100010 ; 50 const double eps = 1e-8 ; 51 const int iinf = INT_MAX ; 52 const ll linf = 2e18 ; 53 const double dinf = 1e30 ; 54 const int MOD = 1000000007 ; 55 56 inline int read(){ 57 int X = 0, w = 0 ; 58 char ch = 0 ; 59 while (!isdigit(ch)) { w |= ch == '-' ; ch = getchar() ; } 60 while (isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar() ; 61 return w ? - X : X ; 62 } 63 64 void write(int x){ 65 if (x < 0) putchar('-'), x = - x ; 66 if (x > 9) write(x / 10) ; 67 putchar(x % 10 + '0') ; 68 } 69 70 void print(int x) { 71 cout << x << endl ; 72 exit(0) ; 73 } 74 75 void PRINT(string x) { 76 cout << x << endl ; 77 exit(0) ; 78 } 79 80 void douout(double x){ 81 printf("%lf\n", x + 0.0000000001) ; 82 } 83 84 struct node { 85 int val, id ; 86 } a[N] ; 87 88 int n, cnt, ans = 1 ; 89 int vis[N] ; 90 91 bool cmp(node a, node b) { 92 if (a.val != b.val) return a.val < b.val ; 93 else return a.id < b.id ; 94 } 95 96 signed main(){ 97 freopen("sort.in", "r", stdin) ; 98 freopen("sort.out", "w", stdout) ; 99 scanf("%d", &n) ; 100 for (int i = 1; i <= n; i++) scanf("%d", &a[i].val), a[i].id = i ; 101 sort(a + 1, a + n + 1, cmp) ; 102 for (int i = 1; i <= n; i++) { 103 if (a[i].id > i) cnt++ ; 104 if (vis[i]) cnt-- ; 105 vis[a[i].id] = 1 ; 106 ans = max(ans, cnt) ; 107 } 108 printf("%d\n", ans) ; 109 } 110 111 /* 112 写代码时请注意: 113 1.是否要开Long Long?数组边界处理好了么? 114 2.实数精度有没有处理? 115 3.特殊情况处理好了么? 116 4.做一些总比不做好。 117 思考提醒: 118 1.最大值和最小值问题可不可以用二分答案? 119 2.有没有贪心策略?否则能不能dp? 120 */
P2 Milking Order
就是有一些任务先后完成要求,求最多能够完成的前多少个任务,但是答案要输出的是方案
一看就是二分+拓扑把
二分能否完成前x个,拓扑判断是否答案是n个,拓扑时把queue改成priority_queue
没什么可讲的吧,就是写基本操作
1 #include <map> 2 #include <set> 3 #include <cmath> 4 #include <ctime> 5 #include <queue> 6 #include <stack> 7 #include <vector> 8 #include <bitset> 9 #include <cstdio> 10 #include <cctype> 11 #include <string> 12 #include <cstring> 13 #include <cassert> 14 #include <climits> 15 #include <cstdlib> 16 #include <iostream> 17 #include <algorithm> 18 #include <functional> 19 using namespace std ; 20 21 #define rep(i, a, b) for (int (i) = (a); (i) <= (b); (i)++) 22 #define Rep(i, a, b) for (int (i) = (a) - 1; (i) < (b); (i)++) 23 #define REP(i, a, b) for (int (i) = (a); (i) >= (b); (i)--) 24 #define clr(a) memset(a, 0, sizeof(a)) 25 #define Sort(a, len, cmp) sort(a + 1, a + len + 1, cmp) 26 #define ass(a, sum) memset(a, sum, sizeof(a)) 27 28 #define ls ((rt) << 1) 29 #define rs ((rt) << 1 | 1) 30 #define lowbit(x) (x & -x) 31 #define mp make_pair 32 #define pb push_back 33 #define fi first 34 #define se second 35 #define endl '\n' 36 #define ENDL cout << endl 37 #define SZ(x) ((int)x.size()) 38 39 typedef long long ll ; 40 typedef unsigned long long ull ; 41 typedef vector <int> vi ; 42 typedef pair <int, int> pii ; 43 typedef pair <ll, ll> pll ; 44 typedef map <int, int> mii ; 45 typedef map <string, int> msi ; 46 typedef map <ll, ll> mll ; 47 48 const int N = 100010 ; 49 const int M = 200010 ; 50 const double eps = 1e-8 ; 51 const int iinf = INT_MAX ; 52 const ll linf = 2e18 ; 53 const double dinf = 1e30 ; 54 const int MOD = 1000000007 ; 55 56 inline int read(){ 57 int X = 0, w = 0 ; 58 char ch = 0 ; 59 while (!isdigit(ch)) { w |= ch == '-' ; ch = getchar() ; } 60 while (isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar() ; 61 return w ? - X : X ; 62 } 63 64 void write(int x){ 65 if (x < 0) putchar('-'), x = - x ; 66 if (x > 9) write(x / 10) ; 67 putchar(x % 10 + '0') ; 68 } 69 70 void print(int x) { 71 cout << x << endl ; 72 exit(0) ; 73 } 74 75 void PRINT(string x) { 76 cout << x << endl ; 77 exit(0) ; 78 } 79 80 void douout(double x){ 81 printf("%lf\n", x + 0.0000000001) ; 82 } 83 84 int n, m, top = 1, cnt, res ; 85 int ans[N], tmp[N], vis[N], head[N], in[N] ; 86 vi v[N] ; 87 88 struct Edge { 89 int to, nxt ; 90 } e[M << 1] ; 91 92 void add(int a, int b) { 93 e[++top] = (Edge) {b, head[a]} ; 94 head[a] = top ; 95 } 96 97 int check(int x) { 98 clr(head) ; clr(in) ; clr(tmp) ; clr(vis); cnt = 0 ; 99 for (int i = 1; i <= x; i++) 100 for (int j = 0; j < SZ(v[i]) - 1; j++) { 101 add(v[i][j], v[i][j + 1]) ; 102 in[v[i][j + 1]]++ ; 103 } 104 priority_queue <int, vi, greater<int> > q ; 105 for (int i = 1; i <= n; i++) if (!in[i]) q.push(i) ; 106 while (!q.empty()) { 107 int now = q.top() ; q.pop() ; 108 vis[now] = 1 ; 109 tmp[++cnt] = now ; 110 for (int i = head[now]; i; i = e[i].nxt){ 111 int to = e[i].to ; 112 if (vis[to]) continue ; 113 in[to]-- ; 114 if (!in[to]) q.push(to) ; 115 } 116 } 117 if (cnt == n) return true ; 118 else return false ; 119 } 120 121 void findans() { 122 clr(head) ; clr(in) ; clr(tmp) ; clr(vis); cnt = 0 ; 123 for (int i = 1; i <= res; i++) 124 for (int j = 0; j < SZ(v[i]) - 1; j++) { 125 add(v[i][j], v[i][j + 1]) ; 126 in[v[i][j + 1]]++ ; 127 } 128 priority_queue <int, vi, greater<int> > q ; 129 for (int i = 1; i <= n; i++) if (!in[i]) q.push(i) ; 130 while (!q.empty()) { 131 int now = q.top() ; q.pop() ; 132 vis[now] = 1 ; 133 tmp[++cnt] = now ; 134 for (int i = head[now]; i; i = e[i].nxt){ 135 int to = e[i].to ; 136 if (vis[to]) continue ; 137 in[to]-- ; 138 if (!in[to]) q.push(to) ; 139 } 140 } 141 for (int i = 1; i < n; i++) printf("%d ", tmp[i]) ; printf("%d\n", tmp[n]) ; 142 } 143 144 signed main(){ 145 freopen("milkorder.in", "r", stdin) ; 146 freopen("milkorder.out", "w", stdout) ; 147 scanf("%d%d", &n, &m) ; 148 for (int i = 1, p; i <= m; i++) { 149 scanf("%d", &p) ; 150 for (int j = 1, x; j <= p; j++) scanf("%d", &x), v[i].pb(x) ; 151 } 152 int l = 0, r = m + 1 ; 153 while (l <= r) { 154 int mid = (l + r) >> 1 ; 155 if (check(mid)) l = mid + 1, res = mid ; 156 else r = mid - 1 ; 157 } 158 findans() ; 159 } 160 161 /* 162 写代码时请注意: 163 1.是否要开Long Long?数组边界处理好了么? 164 2.实数精度有没有处理? 165 3.特殊情况处理好了么? 166 4.做一些总比不做好。 167 思考提醒: 168 1.最大值和最小值问题可不可以用二分答案? 169 2.有没有贪心策略?否则能不能dp? 170 */
P3 Talent Shows
先是01规划+二分,然后乱搞个01背包就过了???666
x[i]表示的是这一头牛拿不拿,如果拿赋值成1,不拿就是0
那么则有答案$R=∑(t[i]*x[i])/∑(w[i]*x[i])$我们需要R最大,现在我们假设有一个没那么优的答案Z满足Z<=R,那么就会有如下的式子:
$∑(t[i]*x[i])>=∑(w[i]*x[i])*Z$
也就是$∑((t[i]-w[i])*x[i]*Z)>=0$
f[i]表示当前选择的奶牛总质量为i时$∑(t[i]-w[i])*x[i]*Z$最大是多少
01背包滚动一下,就AC了
1 #include <map> 2 #include <set> 3 #include <cmath> 4 #include <ctime> 5 #include <queue> 6 #include <stack> 7 #include <vector> 8 #include <bitset> 9 #include <cstdio> 10 #include <cctype> 11 #include <string> 12 #include <cstring> 13 #include <cassert> 14 #include <climits> 15 #include <cstdlib> 16 #include <iostream> 17 #include <algorithm> 18 #include <functional> 19 using namespace std ; 20 21 #define rep(i, a, b) for (int (i) = (a); (i) <= (b); (i)++) 22 #define Rep(i, a, b) for (int (i) = (a) - 1; (i) < (b); (i)++) 23 #define REP(i, a, b) for (int (i) = (a); (i) >= (b); (i)--) 24 #define clr(a) memset(a, 0, sizeof(a)) 25 #define Sort(a, len, cmp) sort(a + 1, a + len + 1, cmp) 26 #define ass(a, sum) memset(a, sum, sizeof(a)) 27 28 #define ls ((rt) << 1) 29 #define rs ((rt) << 1 | 1) 30 #define lowbit(x) (x & -x) 31 #define mp make_pair 32 #define pb push_back 33 #define fi first 34 #define se second 35 #define endl '\n' 36 #define ENDL cout << endl 37 #define SZ(x) ((int)x.size()) 38 39 typedef long long ll ; 40 typedef unsigned long long ull ; 41 typedef vector <int> Vi ; 42 typedef pair <int, int> Pii ; 43 typedef pair <ll, ll> Pll ; 44 typedef map <int, int> mii ; 45 typedef map <string, int> msi ; 46 typedef map <ll, ll> mll ; 47 48 const int N = 1000100 ; 49 const double eps = 1e-8 ; 50 const int iinf = INT_MAX ; 51 const ll linf = 2e18 ; 52 const double dinf = 1e30 ; 53 const int MOD = 1000000007 ; 54 55 inline int read(){ 56 int X = 0, w = 0 ; 57 char ch = 0 ; 58 while (!isdigit(ch)) { w |= ch == '-' ; ch = getchar() ; } 59 while (isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar() ; 60 return w ? - X : X ; 61 } 62 63 void write(int x){ 64 if (x < 0) putchar('-'), x = - x ; 65 if (x > 9) write(x / 10) ; 66 putchar(x % 10 + '0') ; 67 } 68 69 void print(int x) { 70 cout << x << endl ; 71 exit(0) ; 72 } 73 74 void PRINT(string x) { 75 cout << x << endl ; 76 exit(0) ; 77 } 78 79 void douout(double x){ 80 printf("%lf\n", x + 0.0000000001) ; 81 } 82 83 int dp[N], t[N], w[N] ; 84 int n, W ; 85 86 bool check(int x) { 87 ass(dp, 128) ; 88 dp[0] = 0 ; 89 ll tmp = dp[W] ; 90 for (int i = 1; i <= n; i++) // 滚动 91 for (int j = W; j >= 0; j--) 92 if (dp[j] != tmp){ 93 int jj = min(j + w[i], W) ; 94 dp[jj] = max(1ll * dp[jj], dp[j] + t[i] - 1ll * w[i] * x) ; 95 } 96 return dp[W] >= 0 ; 97 } 98 99 int Binary() { 100 int l = 0, r = 1e6 ; 101 while (l <= r) { 102 int mid = (l + r) >> 1 ; 103 if (check(mid)) l = mid + 1 ; 104 else r = mid - 1 ; 105 } 106 return l - 1 ; 107 } 108 109 signed main(){ 110 freopen("talent.in", "r", stdin) ; 111 freopen("talent.out", "w", stdout) ; 112 scanf("%d%d", &n, &W) ; 113 for (int i = 1; i <= n; i++) { 114 scanf("%d%d", &w[i], &t[i]) ; 115 t[i] *= 1000 ; 116 } 117 printf("%d\n", Binary()) ; 118 } 119 120 /* 121 写代码时请注意: 122 1.是否要开Long Long?数组边界处理好了么? 123 2.实数精度有没有处理? 124 3.特殊情况处理好了么? 125 4.做一些总比不做好。 126 思考提醒: 127 1.最大值和最小值问题可不可以用二分答案? 128 2.有没有贪心策略?否则能不能dp? 129 */
总之还是easy的把。
加油ヾ(◍°∇°◍)ノ゙