zoukankan      html  css  js  c++  java
  • 西北大学2019春季校赛题解简录

    提交传送门,密码:jwjtxdy(鸡尾酒天下第一)

    官方题解

    A.二分答案,里面用队列模拟。

     1 #pragma comment(linker, "/STACK:1024000000,1024000000")
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <cstdlib>
     5 #include <cmath>
     6 #include <ctime>
     7 #include <cctype>
     8 #include <climits>
     9 #include <iostream>
    10 #include <iomanip>
    11 #include <algorithm>
    12 #include <string>
    13 #include <sstream>
    14 #include <stack>
    15 #include <queue>
    16 #include <set>
    17 #include <map>
    18 #include <vector>
    19 #include <list>
    20 #include <fstream>
    21 #include <bitset>
    22 #define init(a, b) memset(a, b, sizeof(a))
    23 #define rep(i, a, b) for (int i = a; i <= b; i++)
    24 #define irep(i, a, b) for (int i = a; i >= b; i--)
    25 using namespace std;
    26 
    27 typedef double db;
    28 typedef long long ll;
    29 typedef unsigned long long ull;
    30 typedef pair<int, int> P;
    31 const int inf = 0x3f3f3f3f;
    32 const ll INF = 1e18;
    33 
    34 template <typename T> void read(T &x) {
    35     x = 0;
    36     int s = 1, c = getchar();
    37     for (; !isdigit(c); c = getchar())
    38         if (c == '-')    s = -1;
    39     for (; isdigit(c); c = getchar())
    40         x = x * 10 + c - 48;
    41     x *= s;
    42 }
    43 
    44 template <typename T> void write(T x) {
    45     if (x < 0)    x = -x, putchar('-');
    46     if (x > 9)    write(x / 10);
    47     putchar(x % 10 + '0');
    48 }
    49 
    50 template <typename T> void writeln(T x) {
    51     write(x);
    52     puts("");
    53 }
    54 
    55 const int maxn = 2e5 + 5;
    56 int n, m, t, d;
    57 ll sum[maxn];
    58 P p[maxn];
    59 
    60 bool ok(int cnt) {
    61     init(sum, 0);
    62     queue<int> Q;
    63     rep(i, 1, n) {
    64         while (!Q.empty() && Q.front() + t <= p[i].first) {
    65             Q.pop();
    66             cnt++;
    67         }
    68         if (!cnt) {
    69             sum[p[i].second] += Q.front() + t - p[i].first;
    70             cnt++;
    71             Q.push(Q.front() + t);
    72             Q.pop();
    73         } else  Q.push(p[i].first);
    74         cnt--;
    75     }
    76     rep(i, 1, m)    if (sum[i] >= d)    return false;
    77     return true;
    78 }
    79 
    80 int main() {
    81     read(n), read(m), read(t), read(d);
    82     if (!n || !m) {
    83         puts("0");
    84         return 0;
    85     }
    86     rep(i, 1, n)    read(p[i].first), read(p[i].second);
    87     sort(p + 1, p + 1 + n);
    88     int l = 1, r = n, ans = 0;
    89     while (l < r) {
    90         int mid = (l + r) >> 1;
    91         if (ok(mid)) {
    92             ans = mid;
    93             r = mid;
    94         } else  l = mid + 1;
    95     }
    96     if (ok(r))  ans = r;
    97     writeln(ans);
    98     return 0;
    99 }
    A

    B.因为最后一定会有一个差为m的上下界,枚举下界,然后里面列一列式子发现为了数学算出结果,之前用前缀和预处理一下。

     1 #pragma comment(linker, "/STACK:1024000000,1024000000")
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <cstdlib>
     5 #include <cmath>
     6 #include <ctime>
     7 #include <cctype>
     8 #include <climits>
     9 #include <iostream>
    10 #include <iomanip>
    11 #include <algorithm>
    12 #include <string>
    13 #include <sstream>
    14 #include <stack>
    15 #include <queue>
    16 #include <set>
    17 #include <map>
    18 #include <vector>
    19 #include <list>
    20 #include <fstream>
    21 #include <bitset>
    22 #define init(a, b) memset(a, b, sizeof(a))
    23 #define rep(i, a, b) for (int i = a; i <= b; i++)
    24 #define irep(i, a, b) for (int i = a; i >= b; i--)
    25 using namespace std;
    26 
    27 typedef double db;
    28 typedef long long ll;
    29 typedef unsigned long long ull;
    30 typedef pair<int, int> P;
    31 const int inf = 0x3f3f3f3f;
    32 const ll INF = 1e18;
    33 
    34 template <typename T> void read(T &x) {
    35     x = 0;
    36     int s = 1, c = getchar();
    37     for (; !isdigit(c); c = getchar())
    38         if (c == '-')    s = -1;
    39     for (; isdigit(c); c = getchar())
    40         x = x * 10 + c - 48;
    41     x *= s;
    42 }
    43 
    44 template <typename T> void write(T x) {
    45     if (x < 0)    x = -x, putchar('-');
    46     if (x > 9)    write(x / 10);
    47     putchar(x % 10 + '0');
    48 }
    49 
    50 template <typename T> void writeln(T x) {
    51     write(x);
    52     puts("");
    53 }
    54 
    55 const int maxn = 2e5 + 5;
    56 int n, m, a[maxn];
    57 ll sum1[maxn], sum2[maxn], ans = INF;
    58 
    59 inline ll sqr(int a) { return  (ll)a * a; }
    60 
    61 inline ll calc(int tmp) {
    62     ll ret = 0;
    63     int low = lower_bound(a + 1, a + 1 + n, tmp) - a - 1;
    64     int high = upper_bound(a + 1, a + 1 + n, tmp + m) - a - 1;
    65     ret += sqr(tmp) * low + sum2[low] - (ll)2 * tmp * sum1[low];
    66     ret += sqr(tmp + m) * (n - high) + sum2[n] - sum2[high] - (ll)2 * (tmp + m) * (sum1[n] - sum1[high]);
    67     return ret;
    68 }
    69 
    70 int main() {
    71     read(n), read(m);
    72     rep(i, 1, n)    read(a[i]);
    73     sort(a + 1, a + 1 + n);
    74     rep(i, 1, n) {
    75         sum1[i] = sum1[i - 1] + a[i];
    76         sum2[i] = sum2[i - 1] + sqr(a[i]);
    77     }
    78     for (int i = 0; i + m <= maxn - 5; i++)
    79         ans = min(ans, calc(i));
    80     writeln(ans);
    81     return 0;
    82 }
    B

    C.毒瘤模拟,我要了数据才过去呜呜。

    OX.

    OOX

    X..

    这个数据可以hack一些AC代码,会发现用X去堵住O以后他双杀……我这份也能hack但是我实在懒得改233

     1 #include <cstdio>
     2 #include <cstring>
     3 
     4 int chess[4][4], B, W;
     5 
     6 int main() {
     7     for (int i = 1; i <= 3; i++) {
     8         for (int j = 1; j <= 3; j++) {
     9             char c = getchar();
    10             if (c == 'X')   chess[i][j] = 10, B++;
    11             else if (c == 'O')  chess[i][j] = -10, W++;
    12             else    chess[i][j] = -500;
    13         }
    14         getchar();
    15     }
    16 
    17     auto Go = []() {
    18         if (B - W > 1 || W - B > 0) return -2;
    19         int tmp3 = 0, tmp4 = 0, numb = 0, numw = 0;
    20         bool b1 = false, b2 = false;
    21         for (int i = 1; i <= 3; i++) {
    22             int tmp1 = 0, tmp2 = 0;
    23             for (int j = 1; j <= 3; j++) {
    24                 tmp1 += chess[i][j];
    25                 tmp2 += chess[j][i];
    26                 if (i == j) tmp3 += chess[i][j];
    27                 if (i + j == 4) tmp4 += chess[i][j];
    28             }
    29             if (tmp1 == -30 || tmp2 == -30 || tmp3 == -30 || tmp4 == -30) b1 = true;
    30             if (tmp1 == 30 || tmp2 == 30 || tmp3 == 30 || tmp4 == 30) b2 = true;
    31             numb += (tmp1 == -480) + (tmp2 == -480) + (tmp3 == -480) + (tmp4 == -480);
    32             numw += (tmp1 == -520) + (tmp2 == -520) + (tmp3 == -520) + (tmp4 == -520);
    33         }
    34 
    35         if (b1 && b2)   return -2;
    36         else if (b1) {
    37             if (B == W) return -1;
    38             else    return -2;
    39         }
    40         else if (b2) {
    41             if (B > W)  return 1;
    42             else    return -2;
    43         }
    44         else {
    45             if (B > W) {
    46                 if (numw > 0)   return -1;
    47                 else if (numb > 1)  return 1;
    48                 else    return 0;
    49             } else {
    50                 if (numb > 0)   return 1;
    51                 else if (numw > 1)  return -1;
    52                 else    return 0;
    53             }
    54         }
    55     };
    56 
    57     int flag = Go();
    58     if (flag == -2)  puts("impossible");
    59     else if (flag == -1)    puts("W");
    60     else if (flag == 0) puts("draw");
    61     else    puts("B");
    62 
    63     return 0;
    64 }
    C

    D.dp,如果连不上3个以上的话当前这个就是没价值的,所以枚举左边,然后把中间不是这个的都删了算一下。O(n)的做法大概是边走边记录位置然后直接选取最好的?咕咕

     1 #include <cstdio>
     2 #include <cstring>
     3 #define max(a, b)   a > b ? a : b
     4 
     5 typedef long long ll;
     6 const int maxn = 2050;
     7 int n, a[maxn], sec[6], thi[6], num[6][maxn];
     8 ll dp[maxn];
     9 char str[maxn];
    10 
    11 int main() {
    12     scanf("%d", &n);
    13     for (int i = 1; i <= 5; ++i) {
    14         scanf("%d", &sec[i]);
    15     }
    16     for (int i = 1; i <= 5; ++i) {
    17         scanf("%d", &thi[i]);
    18     }
    19     scanf("%s", str + 1);
    20     for (int i = 1; str[i]; ++i) {
    21         a[i] = str[i] - 'A' + 1;
    22     }
    23 
    24     for (int i = 1; i <= 5; i++) {
    25         for (int j = 1; j <= n; j++) {
    26             num[i][j] = num[i][j - 1] + (a[j] == i);
    27         }
    28     }
    29 
    30     auto calc = [](const int k, const int cnt) {
    31         if (cnt < 3)    return 0ll;
    32         if ((ll)sec[k] * 3 >= thi[k])   return (ll)cnt / 3 * sec[k];
    33         return (ll)thi[k] * (cnt / 9) + (ll)sec[k] * (cnt % 9 / 3);
    34     };
    35     for (int i = 1; i <= n; ++i) {
    36         for (int j = 1; j <= i; ++j) {
    37             if (a[j] == a[i]) {
    38                 dp[i] = max(dp[i], dp[j - 1] + calc(a[i], num[a[i]][i] - num[a[i]][j - 1]));
    39             }
    40         }
    41     }
    42 
    43     printf("%lld
    ", dp[n]);
    44     return 0;
    45 }
    D

    E.可删除并查集。cf上见过类似的。一是操作二如果自己剥离出去自成一派需要新开点;二是加的虚点如果孩子为空了最后扫的时候要删,这两个点WA了我半天。可以像官方题解一样需要的时候再新开点,我一开始就开了n个感觉好丑……

      1 #pragma comment(linker, "/STACK:1024000000,1024000000")
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <cstdlib>
      5 #include <cmath>
      6 #include <ctime>
      7 #include <cctype>
      8 #include <climits>
      9 #include <iostream>
     10 #include <iomanip>
     11 #include <algorithm>
     12 #include <string>
     13 #include <sstream>
     14 #include <stack>
     15 #include <queue>
     16 #include <set>
     17 #include <map>
     18 #include <vector>
     19 #include <list>
     20 #include <fstream>
     21 #include <bitset>
     22 #define init(a, b) memset(a, b, sizeof(a))
     23 #define rep(i, a, b) for (int i = a; i <= b; i++)
     24 #define irep(i, a, b) for (int i = a; i >= b; i--)
     25 using namespace std;
     26 
     27 typedef double db;
     28 typedef long long ll;
     29 typedef unsigned long long ull;
     30 typedef pair<int, int> P;
     31 const int inf = 0x3f3f3f3f;
     32 const ll INF = 1e18;
     33 
     34 template <typename T> void read(T &x) {
     35     x = 0;
     36     int s = 1, c = getchar();
     37     for (; !isdigit(c); c = getchar())
     38         if (c == '-')    s = -1;
     39     for (; isdigit(c); c = getchar())
     40         x = x * 10 + c - 48;
     41     x *= s;
     42 }
     43 
     44 template <typename T> void write(T x) {
     45     if (x < 0)    x = -x, putchar('-');
     46     if (x > 9)    write(x / 10);
     47     putchar(x % 10 + '0');
     48 }
     49 
     50 template <typename T> void writeln(T x) {
     51     write(x);
     52     puts("");
     53 }
     54 
     55 const int maxn = 1e6 + 5;
     56 int n, m, ans = -1, f[maxn * 3], cnt[maxn * 3], extra;
     57 int u[maxn], v[maxn], tot;
     58 bool mark[maxn * 3];
     59 
     60 inline int fa(int v) {
     61     return v == f[v] ? v : f[v] = fa(f[v]);
     62 }
     63 
     64 int main() {
     65     read(n), read(m);
     66     rep(i, 1, n)    f[i] = f[n + i] = n + i, cnt[n + i] = 1;
     67     rep(i, 1, m) {
     68         int op, a, b;
     69         read(op);
     70         if (op == 1) {
     71             read(a), read(b);
     72             int t = fa(a), p = fa(b);
     73             if (t != p) {
     74                 cnt[p] += cnt[t];
     75                 cnt[t] = 0;
     76                 f[t] = p;
     77             }
     78         } else if (op == 2) {
     79             read(a), read(b);
     80             int t = fa(a), p = fa(b);
     81             if (a == b) {
     82                 cnt[t]--;
     83                 ++extra;
     84                 f[a] = f[2 * n + extra] = 2 * n + extra;
     85                 cnt[f[a]] = 1;
     86             } else {
     87                 f[a] = p;
     88                 cnt[t]--, cnt[p]++;
     89             }
     90         } else if (op == 3) {
     91             read(a);
     92             writeln(cnt[fa(a)] - 1);
     93         } else if (op == 4) {
     94             read(a), read(b);
     95             if (fa(a) == fa(b)) puts("Yes");
     96             else    puts("No");
     97         } else {
     98             read(a), read(b);
     99             u[++tot] = a, v[tot] = b;
    100         }
    101     }
    102     rep(i, 1, tot) {
    103         int t = fa(u[i]), p = fa(v[i]);
    104         if (t == p) mark[t] = true;
    105     }
    106     rep(i, 1 + n, n + n + extra) {
    107         if (f[i] == i && cnt[i] && !mark[i])  ans = max(ans, cnt[i]);
    108     }
    109     writeln(ans);
    110     return 0;
    111 }
    E

     Update:改了改新的写法:

      1 #pragma comment(linker, "/STACK:1024000000,1024000000")
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <cstdlib>
      5 #include <cmath>
      6 #include <ctime>
      7 #include <cctype>
      8 #include <climits>
      9 #include <iostream>
     10 #include <iomanip>
     11 #include <algorithm>
     12 #include <string>
     13 #include <sstream>
     14 #include <stack>
     15 #include <queue>
     16 #include <set>
     17 #include <map>
     18 #include <vector>
     19 #include <list>
     20 #include <fstream>
     21 #include <bitset>
     22 #define init(a, b) memset(a, b, sizeof(a))
     23 #define rep(i, a, b) for (int i = a; i <= b; i++)
     24 #define irep(i, a, b) for (int i = a; i >= b; i--)
     25 using namespace std;
     26 
     27 typedef double db;
     28 typedef long long ll;
     29 typedef unsigned long long ull;
     30 typedef pair<int, int> P;
     31 const int inf = 0x3f3f3f3f;
     32 const ll INF = 1e18;
     33 
     34 template <typename T> void read(T &x) {
     35     x = 0;
     36     int s = 1, c = getchar();
     37     for (; !isdigit(c); c = getchar())
     38         if (c == '-')    s = -1;
     39     for (; isdigit(c); c = getchar())
     40         x = x * 10 + c - 48;
     41     x *= s;
     42 }
     43 
     44 template <typename T> void write(T x) {
     45     if (x < 0)    x = -x, putchar('-');
     46     if (x > 9)    write(x / 10);
     47     putchar(x % 10 + '0');
     48 }
     49 
     50 template <typename T> void writeln(T x) {
     51     write(x);
     52     puts("");
     53 }
     54 
     55 const int maxn = 1e6 + 5;
     56 int n, m, ans = -1, f[maxn * 2], New[maxn * 2], cnt[maxn * 2], extra;
     57 int u[maxn], v[maxn], tot;
     58 bool mark[maxn * 2];
     59 
     60 inline int fa(int v) {
     61     return v == f[v] ? v : f[v] = fa(f[v]);
     62 }
     63 
     64 int main() {
     65     read(n), read(m);
     66     extra = n;
     67     rep(i, 1, n)    f[i] = New[i] = i, cnt[i] = 1;
     68     rep(i, 1, m) {
     69         int op, a, b;
     70         read(op);
     71         if (op == 1) {
     72             read(a), read(b);
     73             int t = fa(New[a]), p = fa(New[b]);
     74             if (t != p) {
     75                 cnt[p] += cnt[t];
     76                 cnt[t] = 0;
     77                 f[t] = p;
     78             }
     79         } else if (op == 2) {
     80             read(a), read(b);
     81             int t = fa(New[a]), p = fa(New[b]);
     82             cnt[t]--;
     83             New[a] = ++extra;
     84             f[New[a]] = extra;
     85             if (a != b) {
     86                 f[p] = extra;
     87                 cnt[extra] += cnt[p] + 1;
     88                    cnt[p] = 0;
     89             } else    cnt[extra] = 1;
     90         } else if (op == 3) {
     91             read(a);
     92             writeln(cnt[fa(New[a])] - 1);
     93         } else if (op == 4) {
     94             read(a), read(b);
     95             if (fa(New[a]) == fa(New[b])) puts("Yes");
     96             else    puts("No");
     97         } else {
     98             read(a), read(b);
     99             u[++tot] = a, v[tot] = b;
    100         }
    101     }
    102     rep(i, 1, tot) {
    103         int t = fa(New[u[i]]), p = fa(New[v[i]]);
    104         if (t == p) mark[t] = true;
    105     }
    106     rep(i, 1, extra) {
    107         if (f[i] == i && cnt[i] && !mark[i])  ans = max(ans, cnt[i]);
    108     }
    109     writeln(ans);
    110     return 0;
    111 }
    E2

    F.暴力求字典序,方法是深搜试填,如果当前填的小于串里这个位置本来的字符,则后面的直接用组合数算出来。

      1 #pragma comment(linker, "/STACK:1024000000,1024000000")
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <cstdlib>
      5 #include <cmath>
      6 #include <ctime>
      7 #include <cctype>
      8 #include <climits>
      9 #include <iostream>
     10 #include <iomanip>
     11 #include <algorithm>
     12 #include <string>
     13 #include <sstream>
     14 #include <stack>
     15 #include <queue>
     16 #include <set>
     17 #include <map>
     18 #include <vector>
     19 #include <list>
     20 #include <fstream>
     21 #include <bitset>
     22 #define init(a, b) memset(a, b, sizeof(a))
     23 #define rep(i, a, b) for (int i = a; i <= b; i++)
     24 #define irep(i, a, b) for (int i = a; i >= b; i--)
     25 using namespace std;
     26 
     27 typedef double db;
     28 typedef long long ll;
     29 typedef unsigned long long ull;
     30 typedef pair<int, int> P;
     31 const int inf = 0x3f3f3f3f;
     32 const ll INF = 1e18;
     33 
     34 template <typename T> void read(T &x) {
     35     x = 0;
     36     int s = 1, c = getchar();
     37     for (; !isdigit(c); c = getchar())
     38         if (c == '-')    s = -1;
     39     for (; isdigit(c); c = getchar())
     40         x = x * 10 + c - 48;
     41     x *= s;
     42 }
     43 
     44 template <typename T> void write(T x) {
     45     if (x < 0)    x = -x, putchar('-');
     46     if (x > 9)    write(x / 10);
     47     putchar(x % 10 + '0');
     48 }
     49 
     50 template <typename T> void writeln(T x) {
     51     write(x);
     52     puts("");
     53 }
     54 
     55 const int maxn = 2e4 + 5;
     56 const int mod = 1e9 + 7;
     57 int n, num[maxn];
     58 ll fac[maxn], finv[maxn];
     59 string s, t, str;
     60 
     61 ll ksm(ll a, int b) {
     62     ll ret = 1;
     63     for (; b; b >>= 1) {
     64         if (b & 1)  ret = ret * a % mod;
     65         a = a * a % mod;
     66     }
     67     return ret;
     68 }
     69 
     70 void pre() {
     71     fac[0] = finv[0] = 1;
     72     rep(i, 1, n)    fac[i] = fac[i - 1] * i % mod;
     73     finv[n] = ksm(fac[n], mod - 2);
     74     irep(i, n - 1, 1)   finv[i] = finv[i + 1] * (i + 1) % mod;
     75 }
     76 
     77 ll C(int n, int m) {
     78     return fac[n] * finv[n - m] % mod * finv[m] % mod;
     79 }
     80 
     81 int dfs(int pos, int ch) {
     82     if (pos == n - 1)   return 0;
     83     if (pos >= 0 && str[pos] - 'A' > ch) {
     84         int sum = n - 1 - pos;
     85         ll ret = 1ll;
     86         for (int i = 0; i < 26; ++i) {
     87             if (num[i]) {
     88                 ret = (ret * C(sum, num[i])) % mod;
     89                 sum -= num[i];
     90             }
     91         }
     92         return ret;
     93     }
     94 
     95     ll tmp = 0ll;
     96     for (int i = 0; i < 26; ++i) {
     97         if (i <= str[pos + 1] - 'A' && num[i]) {
     98             num[i]--;
     99             tmp = (tmp + dfs(pos + 1, i)) % mod;
    100             num[i]++;
    101         }
    102     }
    103     return tmp;
    104 }
    105 
    106 ll calc(string tmp) {
    107     str = tmp;
    108     init(num, 0);
    109     for (char i : str) 
    110         num[i - 'A']++;
    111     return dfs(-1, 30);
    112 }
    113 
    114 int main() {
    115     cin >> n >> s >> t;
    116     pre();
    117     cout << (calc(s) - calc(t) + mod) % mod << endl;
    118     return 0;
    119 }
    F

    G.裸最短路,点权+边权。

      1 #pragma comment(linker, "/STACK:1024000000,1024000000")
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <cstdlib>
      5 #include <cmath>
      6 #include <ctime>
      7 #include <cctype>
      8 #include <climits>
      9 #include <iostream>
     10 #include <iomanip>
     11 #include <algorithm>
     12 #include <string>
     13 #include <sstream>
     14 #include <stack>
     15 #include <queue>
     16 #include <set>
     17 #include <map>
     18 #include <vector>
     19 #include <list>
     20 #include <fstream>
     21 #include <bitset>
     22 #define init(a, b) memset(a, b, sizeof(a))
     23 #define rep(i, a, b) for (int i = a; i <= b; i++)
     24 #define irep(i, a, b) for (int i = a; i >= b; i--)
     25 using namespace std;
     26 
     27 typedef double db;
     28 typedef long long ll;
     29 typedef unsigned long long ull;
     30 typedef pair<ll, int> P;
     31 const int inf = 0x3f3f3f3f;
     32 const ll INF = 1e18;
     33 
     34 template <typename T> void read(T &x) {
     35     x = 0;
     36     int s = 1, c = getchar();
     37     for (; !isdigit(c); c = getchar())
     38         if (c == '-')    s = -1;
     39     for (; isdigit(c); c = getchar())
     40         x = x * 10 + c - 48;
     41     x *= s;
     42 }
     43 
     44 template <typename T> void write(T x) {
     45     if (x < 0)    x = -x, putchar('-');
     46     if (x > 9)    write(x / 10);
     47     putchar(x % 10 + '0');
     48 }
     49 
     50 template <typename T> void writeln(T x) {
     51     write(x);
     52     puts("");
     53 }
     54 
     55 const int maxn = 2e5 + 5;
     56 vector<int> factor[maxn];
     57 vector<P> Edge[maxn];
     58 int n;
     59 ll dis[maxn], a[maxn];
     60 
     61 inline void pre() {
     62     rep(i, 1, maxn - 5) {
     63         for (int j = i; j <= maxn - 5; j += i) {
     64             factor[j].push_back(i);
     65         }
     66     }
     67 }
     68 
     69 ll dij() {
     70     dis[1] = a[1];
     71     rep(i, 2, n)    dis[i] = INF;
     72     priority_queue<P, vector<P>, greater<P>> Q;
     73     Q.push(P(a[1], 1));
     74     while (!Q.empty()) {
     75         ll d = Q.top().first;
     76         int p = Q.top().second;
     77         Q.pop();
     78         if (dis[p] < d)    continue;
     79         for (P to : Edge[p]) {
     80             if (dis[to.second] > dis[p] + to.first + a[to.second]) {
     81                 dis[to.second] = dis[p] + to.first + a[to.second];
     82                 Q.push(P(dis[to.second], to.second));
     83             }
     84         }
     85     }
     86     return dis[n] == INF ? -1 : dis[n];
     87 }
     88 
     89 int main() {
     90     read(n);
     91     pre();
     92     rep(i, 1, n) {
     93         ll b, c, d;
     94         read(a[i]), read(b), read(c), read(d);
     95         for (int j : factor[c]) {
     96             if (i + j <= n) {
     97                 Edge[i].push_back(P(b, i + j));
     98             } else  break;
     99         }
    100         if (i != d) Edge[i].push_back(P(0, d));
    101     }
    102     cout << dij() << endl;
    103     return 0;
    104 }
    G

    H.思维题。m < n时,对于n个数求前缀和也是n个数,都%m以后必有两相同的,则中间的这段就是可以整除m的;m == n时有可能没有两个相同的,但这时就会必有0,则这段前缀和为答案。所以直接输出Yes即可。

    1 #include <cstdio>
    2 
    3 int main() {
    4       puts("Yes");
    5       return 0;
    6 }
    H

    I.一眼看过去期望dp套路题,然后莽WA了……要最坏排列所以先贪心排序一波。然鹅改完虽然A过去了,好像所有人中只有我不会正着推用了毒瘤的倒推写法?题解怎么一句话就推完了Orz……如果按照gay论课讲的那个几何分布的话好像还蛮有道理?设dp[i]为成功i个的期望步数,如果从i-1成功到达i的概率为p,则dp[i] = (dp[i-1] + 1) / p。

     1 #pragma comment(linker, "/STACK:1024000000,1024000000")
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <cstdlib>
     5 #include <cmath>
     6 #include <ctime>
     7 #include <cctype>
     8 #include <climits>
     9 #include <iostream>
    10 #include <iomanip>
    11 #include <algorithm>
    12 #include <string>
    13 #include <sstream>
    14 #include <stack>
    15 #include <queue>
    16 #include <set>
    17 #include <map>
    18 #include <vector>
    19 #include <list>
    20 #include <fstream>
    21 #include <bitset>
    22 #define init(a, b) memset(a, b, sizeof(a))
    23 #define rep(i, a, b) for (int i = a; i <= b; i++)
    24 #define irep(i, a, b) for (int i = a; i >= b; i--)
    25 using namespace std;
    26 
    27 typedef double db;
    28 typedef long long ll;
    29 typedef unsigned long long ull;
    30 typedef pair<int, int> P;
    31 const int inf = 0x3f3f3f3f;
    32 const ll INF = 1e18;
    33 
    34 template <typename T> void read(T &x) {
    35     x = 0;
    36     int s = 1, c = getchar();
    37     for (; !isdigit(c); c = getchar())
    38         if (c == '-')    s = -1;
    39     for (; isdigit(c); c = getchar())
    40         x = x * 10 + c - 48;
    41     x *= s;
    42 }
    43 
    44 template <typename T> void write(T x) {
    45     if (x < 0)    x = -x, putchar('-');
    46     if (x > 9)    write(x / 10);
    47     putchar(x % 10 + '0');
    48 }
    49 
    50 template <typename T> void writeln(T x) {
    51     write(x);
    52     puts("");
    53 }
    54 
    55 const int maxn = 1e5 + 5;
    56 const int mod = 1e9 + 7;
    57 int n;
    58 struct pai {
    59     int a, b;
    60     bool operator < (const pai& rhs) const {
    61         return (db)a / b > (db)rhs.a / rhs.b;
    62     }
    63 }t[maxn];
    64 int p[maxn], q[maxn];
    65 int A[maxn], B[maxn];
    66 
    67 inline int ksm(int a, int b) {
    68     int res = 1;
    69     for (; b; b >>= 1) {
    70         if (b & 1)  res = (ll)res * a % mod;
    71         a = (ll)a * a % mod;
    72     }
    73     return res;
    74 }
    75 
    76 int main() {
    77     read(n);
    78     rep(i, 0, n - 1) {
    79         read(t[i].a);
    80         read(t[i].b);
    81     }
    82     sort(t, t + n);
    83     rep(i, 0, n - 1) {
    84         int a = t[i].a, b = t[i].b;
    85         p[i] = (ll)a * ksm(b, mod - 2) % mod;
    86         q[i] = (1 - p[i] + mod) % mod;
    87     }
    88 
    89     irep(i, n - 1, 0) {
    90         A[i] = ((ll)p[i] * A[i + 1] % mod + q[i]) % mod;
    91         B[i] = ((ll)p[i] * B[i + 1] + 1) % mod;
    92     }
    93     writeln((ll)B[0] * ksm((1 - A[0] + mod) % mod, mod - 2) % mod);
    94     return 0;
    95 }
    I

    J.线段树维护一下即可。为了能用线段树维护……使用bfs序一下,这样可以p和p的父亲单点修改,p的孩子因为bfs所以都挨着,修改一下这个区间。可以说一说的是val & (val - 1)本质上就是把lowbit减掉,log次操作就归零了,但这道题里好像没用,而且基本上只能暴力修改,不是区间数字都一样的话没法懒标记。然后就是懒标记tag,因为修改值的操作是直接修改成数字所以tag就直接记录这个数字即可,而同时起到一个bool的作用,如果不是-1的话说明这个区间数字都相同,可以迅速修改。

    码量稍大,但思维直观。

      1 #pragma comment(linker, "/STACK:1024000000,1024000000")
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <cstdlib>
      5 #include <cmath>
      6 #include <ctime>
      7 #include <cctype>
      8 #include <climits>
      9 #include <iostream>
     10 #include <iomanip>
     11 #include <algorithm>
     12 #include <string>
     13 #include <sstream>
     14 #include <stack>
     15 #include <queue>
     16 #include <set>
     17 #include <map>
     18 #include <vector>
     19 #include <list>
     20 #include <fstream>
     21 #include <bitset>
     22 #define init(a, b) memset(a, b, sizeof(a))
     23 #define rep(i, a, b) for (int i = a; i <= b; i++)
     24 #define irep(i, a, b) for (int i = a; i >= b; i--)
     25 using namespace std;
     26 
     27 typedef double db;
     28 typedef long long ll;
     29 typedef unsigned long long ull;
     30 typedef pair<int, int> P;
     31 const int inf = 0x3f3f3f3f;
     32 const ll INF = 1e18;
     33 
     34 template <typename T> void read(T &x) {
     35     x = 0;
     36     int s = 1, c = getchar();
     37     for (; !isdigit(c); c = getchar())
     38         if (c == '-')    s = -1;
     39     for (; isdigit(c); c = getchar())
     40         x = x * 10 + c - 48;
     41     x *= s;
     42 }
     43 
     44 template <typename T> void write(T x) {
     45     if (x < 0)    x = -x, putchar('-');
     46     if (x > 9)    write(x / 10);
     47     putchar(x % 10 + '0');
     48 }
     49 
     50 template <typename T> void writeln(T x) {
     51     write(x);
     52     puts("");
     53 }
     54 
     55 const int maxn = 2e5 + 10;
     56 int n, m, val[maxn];
     57 int l[maxn], r[maxn], f[maxn], bfn[maxn], mp[maxn], cnt;
     58 vector<int> Edge[maxn];
     59 
     60 class SegmentTree {
     61 public:
     62     #define ls(p) p << 1
     63     #define rs(p) p << 1 | 1
     64 
     65     struct Node {
     66         int l, r;
     67         ll sum, tag;
     68 
     69         void ud1() {
     70             tag &= tag - 1;
     71             sum = tag * (r - l + 1);
     72         }
     73 
     74         void ud2(ll x) {
     75             tag = x;
     76             sum = x * (r - l + 1);
     77         }
     78     }t[maxn << 2];
     79 
     80     void Push_Up(int p) {
     81         t[p].sum = t[ls(p)].sum + t[rs(p)].sum;
     82         t[p].tag = t[ls(p)].tag == t[rs(p)].tag ? t[ls(p)].tag : -1;
     83     }
     84 
     85     void Push_Down(int p) {
     86         if (t[p].tag >= 0) {
     87             t[ls(p)].ud2(t[p].tag);
     88             t[rs(p)].ud2(t[p].tag);
     89         }
     90     }
     91 
     92     void Build(int l, int r, int p) {
     93         t[p].l = l, t[p].r = r;
     94         if (l == r) {
     95             t[p].sum = t[p].tag = val[mp[l]];
     96             return;
     97         }
     98         int mid = (l + r) >> 1;
     99         Build(l, mid, ls(p));
    100         Build(mid + 1, r, rs(p));
    101         Push_Up(p);
    102     }
    103 
    104     void Update1(int l, int r, int p) {
    105         if (t[p].tag != -1 && l <= t[p].l && t[p].r <= r) {
    106             t[p].ud1();
    107             return;
    108         }
    109         Push_Down(p);
    110         int mid = (t[p].l + t[p].r) >> 1;
    111         if (l <= mid)    Update1(l, r, ls(p));
    112         if (mid < r)     Update1(l, r, rs(p));
    113         Push_Up(p);
    114     }
    115 
    116     void Update2(int l, int r, int p, int k) {
    117         if (l <= t[p].l && t[p].r <= r) {
    118             t[p].ud2(k);
    119             return;
    120         }
    121         Push_Down(p);
    122         int mid = (t[p].l + t[p].r) >> 1;
    123         if (l <= mid)   Update2(l, r, ls(p), k);
    124         if (mid < r)    Update2(l, r, rs(p), k);
    125         Push_Up(p);
    126     }
    127 
    128     ll Query(int l, int r, int p) {
    129         if (l <= t[p].l && t[p].r <= r) {
    130             return t[p].sum;
    131         }
    132         Push_Down(p);
    133         int mid = (t[p].l + t[p].r) >> 1;
    134         ll ret = 0ll;
    135         if (l <= mid)   ret += Query(l, r, ls(p));
    136         if (mid < r)    ret += Query(l, r, rs(p));
    137         Push_Up(p);
    138         return ret;
    139     }
    140 }T;
    141 
    142 void BFS() {
    143     queue<P> Q;
    144     Q.push(P(1, 0));
    145     bfn[1] = ++cnt;
    146     mp[cnt] = 1;
    147     while (!Q.empty()) {
    148         int x = Q.front().first, fa = Q.front().second;
    149         Q.pop();
    150         l[fa] = min(l[fa], bfn[x]);
    151         r[fa] = max(r[fa], bfn[x]);
    152         for (int son : Edge[x]) {
    153             if (son == fa)  continue;
    154             bfn[son] = ++cnt;
    155             mp[cnt] = son;
    156             f[son] = x;
    157             l[x] = r[x] = cnt;
    158             Q.push(P(son, x));
    159         }
    160     }
    161 }
    162 
    163 int main() {
    164     read(n), read(m);
    165     rep(i, 1, n)    read(val[i]);
    166     rep(i, 1, n - 1) {
    167         int u, v;
    168         read(u), read(v);
    169         Edge[u].push_back(v);
    170         Edge[v].push_back(u);
    171     }
    172     BFS();
    173     T.Build(1, n, 1);
    174     rep(i, 1, m) {
    175         int op, p;
    176         read(op), read(p);
    177         if (op == 1) {
    178             T.Update1(bfn[p], bfn[p], 1);
    179             if (f[p])   T.Update1(bfn[f[p]], bfn[f[p]], 1);
    180             if (l[p])   T.Update1(l[p], r[p], 1);
    181         } else if (op == 2) {
    182             ll x;
    183             read(x);
    184             T.Update2(bfn[p], bfn[p], 1, x);
    185             if (f[p])   T.Update2(bfn[f[p]], bfn[f[p]], 1, x);
    186             if (l[p])   T.Update2(l[p], r[p], 1, x);
    187         } else {
    188             ll Q = T.Query(bfn[p], bfn[p], 1);
    189             if (f[p])   Q += T.Query(bfn[f[p]], bfn[f[p]], 1);
    190             if (l[p])   Q += T.Query(l[p], r[p], 1);
    191             writeln(Q);
    192         }
    193     }
    194     return 0;
    195 }
    J

    K.1e18逼我猜结论……好吧小数据脑补一下发现是博弈论中常见的对称手法,如果偶数的话鸡尾酒对称着下,否则沃老师占中,然后也对称着下。

     1 #include <cstdio>
     2 
     3 long long n, m;
     4 
     5 int main() {
     6     scanf("%lld %lld", &n, &m);
     7     n = n % 2 * m % 2;
     8     puts(n ? "wls" : "cocktail");
     9     return 0;
    10 }
    K

    L.差分dp,对我来说最难理解的一道题了嘤嘤嘤。官方题解的dp意义并不常规(常规设到达n的最短时间),而是某个时间点能否到达n。这样就不是像往常一样最后输出一下边界,而是发现dp[i][n]为真直接输出。(看其他大佬AC的代码也有设常规dp的,可做。)

    想了好久细节的部分,其做法的正确性,比如:

    为什么下面需要dp和ok结合判断,输出却不需要ok判断?(注释)

    一些边界情况?(比如刚好可达但却来车了:数据:3 1  2 2 5. 这时应输出7,即使到了2也因为来车了不能转移)

    dp为真ok却为假这样的情况是否只有那一种?(应该是的吧……就是上面这种。否则如果之前ok就是false,l和r延伸时也不可能延伸到这里,故而dp也不会为真)

    加两个虚值的意义以及其值可以随便改吗?(加0时刻才能开始转移;加inf时刻是为了最后时刻的i+1有值可取避免溢出,所以值随便设)

    l和r不初始化也不判定是否会导致错误?(不会,因为没有l、r值的会被ok直接筛下去)

    等等……

    大概当你第一次见到某种精巧的设计之时都会如此懵逼,然而自己还是下次还是设计不出来。

      1 #pragma comment(linker, "/STACK:1024000000,1024000000")
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <cstdlib>
      5 #include <cmath>
      6 #include <ctime>
      7 #include <cctype>
      8 #include <climits>
      9 #include <iostream>
     10 #include <iomanip>
     11 #include <algorithm>
     12 #include <string>
     13 #include <sstream>
     14 #include <stack>
     15 #include <queue>
     16 #include <set>
     17 #include <map>
     18 #include <vector>
     19 #include <list>
     20 #include <fstream>
     21 #include <bitset>
     22 #define init(a, b) memset(a, b, sizeof(a))
     23 #define rep(i, a, b) for (int i = a; i <= b; i++)
     24 #define irep(i, a, b) for (int i = a; i >= b; i--)
     25 using namespace std;
     26 
     27 typedef double db;
     28 typedef long long ll;
     29 typedef unsigned long long ull;
     30 typedef pair<int, int> P;
     31 const int inf = 0x3f3f3f3f;
     32 const ll INF = 1e18;
     33 
     34 template <typename T> void read(T &x) {
     35     x = 0;
     36     int s = 1, c = getchar();
     37     for (; !isdigit(c); c = getchar())
     38         if (c == '-')    s = -1;
     39     for (; isdigit(c); c = getchar())
     40         x = x * 10 + c - 48;
     41     x *= s;
     42 }
     43 
     44 template <typename T> void write(T x) {
     45     if (x < 0)    x = -x, putchar('-');
     46     if (x > 9)    write(x / 10);
     47     putchar(x % 10 + '0');
     48 }
     49 
     50 template <typename T> void writeln(T x) {
     51     write(x);
     52     puts("");
     53 }
     54 
     55 const int maxn = 2e3 + 5;
     56 int n, m;
     57 pair<int, P> p[maxn << 1];
     58 int dp[maxn << 1][maxn], l[maxn], r[maxn];
     59 bool ok[maxn];
     60 
     61 int main() {
     62     read(n), read(m);
     63     rep(i, 1, m) {
     64         int a, b, c;
     65         read(a), read(b), read(c);
     66         p[i * 2 - 1] = make_pair(b, P(a, 0));
     67         p[i * 2] = make_pair(c, P(a, 1));
     68     }
     69     p[0] = make_pair(0, P(0, 1));
     70     p[2 * m + 1] = make_pair((int)1e9 + 5, P(0, 1));
     71     sort(p, p + 2 * m + 2);
     72 
     73     memset(ok, true, sizeof ok);//一开始都是ok的
     74     dp[0][0] = 1, dp[0][1] = -1;
     75     rep(i, 0, 2 * m) {
     76         rep(j, 1, n)    dp[i][j] += dp[i][j - 1];
     77         if (dp[i][n]) {
     78             irep(j, n - 1, 0)    if (dp[i - 1][j]) {
     79             //dp[i][n]可行一定是dp[i-1][j]转移过来的,下边min和max的操作保证了:dp[i][n]可达时,此处不可能存在dp[i-1][j] > 0 && ok[j] = false;
     80                 printf("%d
    ", p[i - 1].first + n - j);
     81                 return 0;
     82             }
     83         }
     84 
     85         ok[p[i].second.first] = p[i].second.second;
     86         int now = 0;
     87         rep(j, 0, n) {
     88             if (ok[j])    l[j] = now;
     89             else    now = j + 1;
     90         }
     91         now = n;
     92         irep(j, n, 0) {
     93             if (ok[j])    r[j] = now;
     94             else    now = j - 1;
     95         }
     96 
     97         rep(j, 0, n) {
     98             if (!dp[i][j] || !ok[j])    continue;//即使j在这一轮可达,如果这时恰好来车了,其实也是不可达
     99             dp[i + 1][max(l[j], j - p[i + 1].first + p[i].first)]++;
    100             dp[i + 1][min(r[j], j + p[i + 1].first - p[i].first) + 1]--;
    101         }
    102     }
    103     irep(j, n, 0)    if (dp[2 * m][j]) {
    104         printf("%d
    ", p[2 * m].first + n - j);
    105         break;//忘写break,WA一小时卧槽
    106     }
    107     return 0;
    108 }
    L

    那么这就是全部的题目了~最强OJ,最强OJ.jpg(逃

  • 相关阅读:
    HOJ 2139 Spiderman's workout(动态规划)
    FZU 2107 Hua Rong Dao(dfs)
    Java 第十一届 蓝桥杯 省模拟赛 计算机存储中有多少字节
    Java 第十一届 蓝桥杯 省模拟赛 计算机存储中有多少字节
    Java 第十一届 蓝桥杯 省模拟赛 计算机存储中有多少字节
    Java 第十一届 蓝桥杯 省模拟赛 合法括号序列
    Java 第十一届 蓝桥杯 省模拟赛 合法括号序列
    Java 第十一届 蓝桥杯 省模拟赛 合法括号序列
    Java 第十一届 蓝桥杯 省模拟赛 无向连通图最少包含多少条边
    Java 第十一届 蓝桥杯 省模拟赛 无向连通图最少包含多少条边
  • 原文地址:https://www.cnblogs.com/AlphaWA/p/10606267.html
Copyright © 2011-2022 走看看