• 西北大学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(逃

  • 相关阅读:
    大神的文章
    分布式锁
    分布式事务
    事务两三事
    spring框架笔记
    三个缓存数据库Redis、Memcache、MongoDB
    面向对象面试题
    SSM面试
    单例模式
    Spring Cloud面试题
  • 原文地址:https://www.cnblogs.com/AlphaWA/p/10606267.html
Copyright © 2020-2023  润新知