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 */
AC CODE

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 */
AC CODE

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 */
AC CODE

总之还是easy的把。

posted @ 2018-11-29 14:43  harryhqg  阅读(464)  评论(0编辑  收藏  举报