agc034

A:题意:你有一个1 * n的网格,有些地方是障碍。你有两个人,分别要从a到b和从c到d,一次只能向右跳1步或者两步。求是否可行。

解:先判断有没有2个连续的障碍,然后判断是否能错车。

 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 }
AC代码

B:题意:你有一个ABC字符串,你能进行的操作就是把某个ABC变成BCA。求最多进行多少次操作。

解:发现可以把BC看做一个整体。单独的B和C看做障碍物。

那么对于每一段无障碍物的连续A,BC,求逆序对就好了。

 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 }
AC代码

C:题意:你有n场考试,满分X分。你的对手每场考试得了bi分。你每学习一个小时就能把某场考试提高1分。你能给每场考试选择一个li~ri之间的加权。求你最少花多少小时才能不比对手考的低。

解:发现加权要么是li要么是ri。且你比对手高就是ri,否则就是li。

然后发现如果有两场考试都没有满分,最优策略是把一场考试的分挪到另一场上。

然后就发现答案一定是若干场满分和一场非满分。这时候就可以排序了,然后二分答案,枚举非满分是哪一场。

 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 }
AC代码

D:题意:给你平面上两组n个点,你要把它们配对,使得曼哈顿距离最大。n <= 1000。

解:曼哈顿距离有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 }
AC代码

 

posted @ 2019-06-06 09:29  huyufeifei  阅读(423)  评论(0编辑  收藏  举报
试着放一个广告栏(虽然没有一分钱广告费)

『Flyable Heart 応援中!』 HHG 高苗京铃 闪十PSS 双六 電動伝奇堂 章鱼罐头制作组 はきか 祝姬 星降夜