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

原文地址:https://www.cnblogs.com/AlphaWA/p/10606267.html