2019牛客暑期多校训练营 第二场

爆炸自闭,题目太难。

题解会一直更新,这场题目太不好补了。

题目链接:https://ac.nowcoder.com/acm/contest/882#question


A:

题解就说是对小数据找规律……证明完全不会。

 1 /* basic header */
 2 #include <bits/stdc++.h>
 3 /* define */
 4 #define ll long long
 5 #define dou double
 6 #define pb emplace_back
 7 #define mp make_pair
 8 #define sot(a,b) sort(a+1,a+1+b)
 9 #define rep1(i,a,b) for(int i=a;i<=b;++i)
10 #define rep0(i,a,b) for(int i=a;i<b;++i)
11 #define eps 1e-8
12 #define int_inf 0x3f3f3f3f
13 #define ll_inf 0x7f7f7f7f7f7f7f7f
14 #define lson (curpos<<1)
15 #define rson (curpos<<1|1)
16 #define mid (curl+curr>>1)
17 /* namespace */
18 using namespace std;
19 /* header end */
20 
21 const ll mod = 1e9 + 7;
22 
23 ll qp(ll x, ll b) {
24     ll ret = 1;
25     while (b) {
26         if (b & 1) ret = ret * x % mod;
27         x = x * x % mod;
28         b >>= 1;
29     }
30     return ret;
31 }
32 
33 ll n, m, ans = 1;
34 
35 int main() {
36     int t; scanf("%d", &t);
37     while (t--) {
38         scanf("%lld%lld", &n, &m);
39         if (n == 1) printf("%lld
", ans);
40         else {
41             if (!m) ans = 0;
42             else ans = ans * qp(n - 1, mod - 2) % mod;
43             printf("%lld
", ans);
44         }
45     }
46     return 0;
47 }
View Code

B:

dp?

C:

贼恐怖的数据结构题,线段树+link-cut tree。

D:

让人自闭的图论题,结果题解就说是暴力。

E:

线段树维护dp,跟昨天的套路一样。

F:

听题解说得特别简单,是组合数暴力,但是有优化技巧。

然而我选择爆搜+剪枝。隔壁队还有模拟退火过的,也是nb。

但是爆搜不是正向爆搜,是反向的。ans=所有competitive value减去队内competitive value

 1 /* basic header */
 2 #include <bits/stdc++.h>
 3 /* define */
 4 #define ll long long
 5 #define dou double
 6 #define pb emplace_back
 7 #define mp make_pair
 8 #define sot(a,b) sort(a+1,a+1+b)
 9 #define rep1(i,a,b) for(int i=a;i<=b;++i)
10 #define rep0(i,a,b) for(int i=a;i<b;++i)
11 #define eps 1e-8
12 #define int_inf 0x3f3f3f3f
13 #define ll_inf 0x7f7f7f7f7f7f7f7f
14 #define lson (curpos<<1)
15 #define rson (curpos<<1|1)
16 #define mid (curl+curr>>1)
17 /* namespace */
18 using namespace std;
19 /* header end */
20 
21 const int maxn = 30;
22 int n, a[maxn], b[maxn], v[maxn][maxn], vis[maxn];
23 ll ans = ll_inf, totCmp = 0;
24 
25 void dfs(int depth, int curr, ll sum) {
26     if (sum >= ans) return;
27     if (depth >= n) {
28         int b0 = b[0];
29         if (b[0] != n)
30             for (int i = a[a[0]] + 1; i < 2 * n; i++) {
31                 for (int j = 1; j <= b[0]; j++) sum += v[i][b[j]];
32                 b[++b[0]] = i;
33             }
34         ans = min(ans, sum);
35         b[0] = b0;
36         return;
37     }
38     ll addB = 0;
39     int a0 = a[0], b0 = b[0];
40     rep1(i, curr, n + depth) {
41         ll addA = 0;
42         rep1(j, 1, a[0]) addA += v[i][a[j]];
43         a[++a[0]] = i;
44         dfs(depth + 1, i + 1, sum + addA + addB);
45         a[0]--;
46         rep1(j, 1, b[0]) addB += v[i][b[j]];
47         b[++b[0]] = i;
48     }
49     a[0] = a0, b[0] = b0;
50 }
51 
52 int main() {
53     memset(vis, 0, sizeof(vis));
54     scanf("%d", &n);
55     rep0(i, 0, 2 * n) {
56         rep0(j, 0, 2 * n)
57         scanf("%d", &v[i][j]);
58     }
59     rep0(i, 0, 2 * n) {
60         rep0(j, i + 1, 2 * n) totCmp += v[i][j];
61     }
62     dfs(0, 0, 0);
63     printf("%lld
", totCmp - ans);
64     return 0;
65 }
View Code

G:

没人做的几何题。

H:

队友做的题。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<vector>
 5 #include<queue>
 6 #include<set>
 7 using namespace std;
 8 const int maxn = 1500;
 9 
10 int M[maxn][maxn];
11 int Link[maxn], Left[maxn], Right[maxn];
12 string s;
13 vector<int> ans;
14 
15 bool CMP(int a, int b) {
16     return a > b;
17 }
18 
19 int main() {
20     int n, m;
21     int fmax = 0, smax = 0;
22     cin >> n >> m;
23     for (int i = 1; i <= n; i++) {
24         cin >> s;
25         for (int j = 1; j <= m; j++) {
26             M[i][j] = s[j - 1] - '0';
27         }
28     }
29     for (int i = 1; i <= m; i++) {
30         Link[i] = 0;
31         Left[i] = 1;
32         Right[i] = m ;
33     }
34     int hight, width;
35     for (int i = 1; i <= n; i++) {
36         int nowl = 0;
37         for (int j = 1; j <= m; j++) {
38             if (M[i][j] == 0) {
39                 Link[j] = 0;
40                 nowl = j;
41                 Left[j] = 1;
42             } else {
43                 Left[j] = max(Left[j], nowl + 1);
44                 Link[j] ++;
45             }
46         }
47         int nowr = m + 1 ;
48         set<int> S;
49         S.clear();
50         for (int j = m; j >= 1; j--) {
51             if (M[i][j] == 0) {
52                 nowr = j ;
53                 Right[j] = m;
54                 S.clear();
55             } else {
56                 Right[j] = min(nowr - 1, Right[j]);
57                 int s = (Link[j] * (Right[j] - Left[j] + 1));
58                 if (S.count(s)) {
59                     continue;
60                 }
61                 S.insert(s);
62                 if (s >= fmax) {
63                     smax = fmax;
64                     fmax = s;
65                     hight = Link[j];
66                     width = (Right[j] - Left[j] + 1);
67                 } else if (s > smax) {
68                     smax = s;
69                 }
70             }
71         }
72     }
73     cout << max(smax, max(hight * (width - 1), (hight - 1) * width)) << endl;
74     return 0;
75 }
View Code

赛后upsolved代码。

 1 /* basic header */
 2 #include <bits/stdc++.h>
 3 /* define */
 4 #define ll long long
 5 #define dou double
 6 #define pb emplace_back
 7 #define mp make_pair
 8 #define sot(a,b) sort(a+1,a+1+b)
 9 #define rep1(i,a,b) for(int i=a;i<=b;++i)
10 #define rep0(i,a,b) for(int i=a;i<b;++i)
11 #define eps 1e-8
12 #define int_inf 0x3f3f3f3f
13 #define ll_inf 0x7f7f7f7f7f7f7f7f
14 #define lson (curpos<<1)
15 #define rson (curpos<<1|1)
16 #define mid (curl+curr>>1)
17 /* namespace */
18 using namespace std;
19 /* header end */
20 
21 const int maxn = 1e3 + 10;
22 char s[maxn][maxn];
23 int h[maxn], n, m, maxx = 0, maxx2 = 0, x, y;
24 
25 int main() {
26     scanf("%d%d", &n, &m);
27     rep0(i, 0, n) scanf("%s", s[i]);
28     rep0(i, 0, n) {
29         rep0(j, 0, m) {
30             if (s[i][j] == '1') h[j]++;
31             else h[j] = 0;
32         }
33         stack<int>q;
34         rep0(j, 0, m) {
35             while (!q.empty() && h[j] <= h[q.top()]) {
36                 int l = q.top();
37                 q.pop();
38                 int k = q.empty() ? -1 : q.top(), sum = (j - k - 1) * h[l];
39                 if (sum > maxx) {
40                     x = j - k - 1;
41                     y = h[l];
42                     maxx2 = maxx; maxx = sum;
43                 } else if (sum > maxx2) maxx2 = sum;
44             }
45             q.push(j);
46         }
47         if (!q.empty()) {
48             int l = q.top();
49             q.pop();
50             int k = q.empty() ? -1 : q.top();
51             int sum = (m - k - 1) * h[l];
52             if (sum > maxx) {
53                 x = m - k - 1;
54                 y = h[l];
55                 maxx2 = maxx; maxx = sum;
56             } else if (sum > maxx2) maxx2 = sum;
57         }
58     }
59     int ans = max(max(maxx - x, maxx - y), maxx2);
60     printf("%d
", ans);
61     return 0;
62 }
View Code

I:

又是dp?题目看懂了,然而一脸懵逼完全不知道怎么做。

J:

开场不知道是哪两个闸总1A,害得我以为是水题(wdnmd)。看了好久才发现开错题。

当时感觉是个数据结构xjb维护,题解居然是暴力……

 1 /* basic header */
 2 #include <bits/stdc++.h>
 3 /* define */
 4 #define ll long long
 5 #define dou double
 6 #define pb emplace_back
 7 #define mp make_pair
 8 #define sot(a,b) sort(a+1,a+1+b)
 9 #define rep1(i,a,b) for(int i=a;i<=b;++i)
10 #define rep0(i,a,b) for(int i=a;i<b;++i)
11 #define eps 1e-8
12 #define int_inf 0x3f3f3f3f
13 #define ll_inf 0x7f7f7f7f7f7f7f7f
14 #define lson (curpos<<1)
15 #define rson (curpos<<1|1)
16 #define mid (curl+curr>>1)
17 /* namespace */
18 using namespace std;
19 /* header end */
20 
21 // const int maxn = 1e6 + 10, maxm = 2e7 + 10;
22 const int maxn = 10, maxm = 20;
23 ll sum = 0;
24 int s[maxm], l[maxn], r[maxn], p[maxn];
25 int n, x = 0, now = 0, zero = 10, k = 0, st = zero, L = zero, R = zero;
26 
27 // 只包含1的区间称为1区间,只包含0的区间称为0区间
28 int main() {
29     scanf("%d", &n);
30     rep1(i, 1, n) scanf("%d%d", &l[i], &r[i]);
31     // p是前缀和,维护当前1区间和前面的0区间抵消之后剩下1的个数
32     rep1(i, 1, n) p[i] = p[i - 1] + (r[i] - l[i] + 1) - (l[i] - r[i - 1] - 1);
33     for (int i = n - 1; i >= 1; i--) p[i] = max(p[i], p[i + 1]);
34     s[zero] = 1;
35     rep1(i, 1, n) {
36         while (x < l[i]) {
37             if (!now && k - p[i] < l[i] && k > p[i]) {
38                 x += k - p[i];
39                 k = p[i];
40                 st = L = zero;
41                 R = zero - 1;
42             }
43             x++, k--, st--;
44             if (st < L) {
45                 L--; s[st] = 0;
46             }
47             now -= s[st]++;
48             sum += now;
49         }
50         while (x <= r[i]) {
51             x++, k++;
52             now += s[st++];
53             sum += now;
54             if (st > R) {
55                 R++;
56                 s[st] = 0;
57             }
58             s[st]++;
59         }
60     }
61     while (now > 0 && x < 1e9 && st >= 0 && st <= 2 * zero) {
62         x++;
63         now -= s[--st]++;
64         sum += now;
65     }
66     printf("%lld
", sum);
67     return 0;
68 }
View Code
原文地址:https://www.cnblogs.com/JHSeng/p/11219830.html