• 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
    ");
    15                 return 0;
    16             }
    17         }
    18         printf("Yes
    ");
    19         return 0;
    20     }
    21     else {
    22         for(int i = a; i < c; i++) {
    23             if(str[i] == '#' && str[i + 1] == '#') {
    24                 printf("No
    ");
    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
    ");
    31                 return 0;
    32             }
    33         }
    34         printf("No
    ");
    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
    ", 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 
    ", 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 
    ", 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
    ", 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
    ", -cost);
    101     return 0;
    102 }
    AC代码
  • 相关阅读:
    数据类型装换
    变量及数据类型
    27 网络通信协议 udp tcp
    26 socket简单操作
    26 socket简单操作
    14 内置函数 递归 二分法查找
    15 装饰器 开闭原则 代参装饰器 多个装饰器同一函数应用
    12 生成器和生成器函数以及各种推导式
    13 内置函数 匿名函数 eval,exec,compile
    10 函数进阶 动态传参 作用域和名称空间 函数的嵌套 全局变量
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/10983191.html
Copyright © 2020-2023  润新知