A:題意:你有一個1 * n的網格,有些地方是障礙。你有兩我的,分別要從a到b和從c到d,一次只能向右跳1步或者兩步。求是否可行。node
解:先判斷有沒有2個連續的障礙,而後判斷是否能錯車。c++
1 #include <bits/stdc++.h> 2 3 const int N = 200010; 4 5 char str[N]; 6 7 int main() { 8 int n, a, b, c, d; 9 scanf("%d%d%d%d%d", &n, &a, &b, &c, &d); 10 scanf("%s", str + 1); 11 if(c < d) { 12 for(int i = a; i < d; i++) { 13 if(str[i] == '#' && str[i + 1] == '#') { 14 printf("No\n"); 15 return 0; 16 } 17 } 18 printf("Yes\n"); 19 return 0; 20 } 21 else { 22 for(int i = a; i < c; i++) { 23 if(str[i] == '#' && str[i + 1] == '#') { 24 printf("No\n"); 25 return 0; 26 } 27 } 28 for(int i = b; i <= d; i++) { 29 if(str[i - 1] == '.' && str[i] == '.' && str[i + 1] == '.') { 30 printf("Yes\n"); 31 return 0; 32 } 33 } 34 printf("No\n"); 35 return 0; 36 } 37 return 0; 38 }
B:題意:你有一個ABC字符串,你能進行的操做就是把某個ABC變成BCA。求最多進行多少次操做。ide
解:發現能夠把BC看作一個總體。單獨的B和C看作障礙物。學習
那麼對於每一段無障礙物的連續A,BC,求逆序對就行了。spa
1 #include <bits/stdc++.h> 2 3 typedef long long LL; 4 const int N = 200010; 5 6 char str[N]; 7 bool vis[N]; 8 9 int main() { 10 11 scanf("%s", str + 1); 12 int n = strlen(str + 1); 13 for(int i = 1; i <= n; i++) { 14 if(str[i] == 'C' && str[i - 1] != 'B') { 15 vis[i] = 1; 16 } 17 if(str[i] == 'B' && str[i + 1] != 'C') { 18 vis[i] = 1; 19 } 20 } 21 LL ans = 0; 22 for(int l = 1, r; l <= n; l = r + 1) { 23 while(vis[l]) { 24 ++l; 25 } 26 if(l > n) break; 27 r = l; 28 while(!vis[r + 1] && r < n) { 29 ++r; 30 } 31 LL cnt = 0, t = 0; 32 for(int i = l; i <= r; i++) { 33 if(str[i] == 'A') { 34 ++cnt; 35 } 36 else if(str[i] == 'B' && str[i + 1] == 'C') { 37 ++i; 38 t += cnt; 39 } 40 } 41 ans += t; 42 } 43 printf("%lld\n", ans); 44 return 0; 45 }
C:題意:你有n場考試,滿分X分。你的對手每場考試得了bi分。你每學習一個小時就能把某場考試提升1分。你能給每場考試選擇一個li~ri之間的加權。求你最少花多少小時才能不比對手考的低。
code
解:發現加權要麼是li要麼是ri。且你比對手高就是ri,不然就是li。blog
而後發現若是有兩場考試都沒有滿分,最優策略是把一場考試的分挪到另外一場上。排序
而後就發現答案必定是若干場滿分和一場非滿分。這時候就能夠排序了,而後二分答案,枚舉非滿分是哪一場。字符串
1 #include <bits/stdc++.h> 2 3 typedef long long LL; 4 const int N = 100010; 5 6 struct Node { 7 LL l, r, b, h; 8 inline bool operator < (const Node &w) const { 9 return h > w.h; 10 } 11 }node[N]; 12 13 LL X, D, sum[N]; 14 int n; 15 16 inline LL cal(LL a, LL i) { 17 if(a <= node[i].b) { 18 return a * node[i].l; 19 } 20 return node[i].b * node[i].l + (a - node[i].b) * node[i].r; 21 } 22 23 inline bool check(LL k) { 24 LL ans = 0, r = k % X, t = k / X; 25 if(t >= n) { 26 return sum[n]; 27 } 28 // printf("r = %lld t = %lld \n", r, t); 29 for(int i = 1; i <= n; i++) { 30 if(i <= t) ans = std::max(ans, cal(r, i) + sum[t + 1] - node[i].h); 31 else { 32 ans = std::max(ans, cal(r, i) + sum[t]); 33 } 34 } 35 //printf("k = %lld ans = %lld D = %lld \n", k, ans, D); 36 return ans >= D; 37 } 38 39 int main() { 40 41 scanf("%d%lld", &n, &X); 42 for(int i = 1; i <= n; i++) { 43 scanf("%lld%lld%lld", &node[i].b, &node[i].l, &node[i].r); 44 node[i].h = node[i].b * node[i].l + (X - node[i].b) * node[i].r; 45 D += node[i].b * node[i].l; 46 } 47 std::sort(node + 1, node + n + 1); 48 for(int i = 1; i <= n; i++) { 49 sum[i] = sum[i - 1] + node[i].h; 50 } 51 LL l = 0, r = 4e18; 52 while(l < r) { 53 LL mid = (l + r) >> 1; 54 if(check(mid)) { 55 r = mid; 56 } 57 else { 58 l = mid + 1; 59 } 60 } 61 printf("%lld\n", r); 62 return 0; 63 }
D:題意:給你平面上兩組n個點,你要把它們配對,使得曼哈頓距離最大。n <= 1000。
it
解:曼哈頓距離有2個絕對值,拆開就是4種狀況。直接建4箇中轉點表示這4種狀況,跑最大費用最大流。
1 #include <bits/stdc++.h> 2 3 #define int LL 4 5 typedef long long LL; 6 const int N = 2010, INF = 0x3f3f3f3f3f3f3f3fll; 7 8 struct Edge { 9 int nex, v, c, len; 10 Edge(){} 11 Edge(int N, int V, int C, int L) { 12 nex = N, v = V, c = C, len = L; 13 } 14 }edge[2000010]; int tp = 1; 15 16 int e[N], n, tot, d[N], pre[N], flow[N], Time, vis[N]; 17 std::queue<int> Q; 18 19 inline void add(int x, int y, int z, int w) { 20 edge[++tp] = Edge(e[x], y, z, w); 21 e[x] = tp; 22 edge[++tp] = Edge(e[y], x, 0, -w); 23 e[y] = tp; 24 return; 25 } 26 27 inline bool SPFA(int s, int t) { 28 memset(d, 0x3f, sizeof(d)); 29 Q.push(s); 30 ++Time; 31 d[s] = 0; 32 vis[s] = Time; 33 flow[s] = INF; 34 while(Q.size()) { 35 int x = Q.front(); 36 Q.pop(); 37 vis[x] = 0; 38 for(int i = e[x]; i; i = edge[i].nex) { 39 int y = edge[i].v; 40 if(edge[i].c && d[y] > d[x] + edge[i].len) { 41 d[y] = d[x] + edge[i].len; 42 pre[y] = i; 43 flow[y] = std::min(flow[x], edge[i].c); 44 if(vis[y] != Time) { 45 vis[y] = Time; 46 Q.push(y); 47 } 48 } 49 } 50 } 51 return d[t] < INF; 52 } 53 54 inline void update(int s, int t) { 55 int f = flow[t]; 56 while(s != t) { 57 int i = pre[t]; 58 edge[i].c -= f; 59 edge[i ^ 1].c += f; 60 t = edge[i ^ 1].v; 61 } 62 return; 63 } 64 65 inline int solve(int s, int t, int &cost) { 66 cost = 0; 67 int ans = 0; 68 while(SPFA(s, t)) { 69 //printf("!"); 70 ans += flow[t]; 71 cost += flow[t] * d[t]; 72 update(s, t); 73 } 74 return ans; 75 } 76 77 signed main() { 78 79 scanf("%lld", &n); 80 int s = 2 * n + 5, t = s + 1, x, y, z; 81 for(int i = 1; i <= n; i++) { 82 scanf("%lld%lld%lld", &x, &y, &z); 83 add(s, i, z, 0); 84 add(i, 2 * n + 1, z, x + y); 85 add(i, 2 * n + 2, z, y - x); 86 add(i, 2 * n + 3, z, x - y); 87 add(i, 2 * n + 4, z, -x - y); 88 } 89 for(int i = 1; i <= n; i++) { 90 scanf("%lld%lld%lld", &x, &y, &z); 91 add(n + i, t, z, 0); 92 add(2 * n + 1, n + i, z, -x - y); 93 add(2 * n + 2, n + i, z, x - y); 94 add(2 * n + 3, n + i, z, y - x); 95 add(2 * n + 4, n + i, z, x + y); 96 } 97 //puts("OVER"); 98 int cost = 0; 99 solve(s, t, cost); 100 printf("%lld\n", -cost); 101 return 0; 102 }