比赛-6月Round1

Posted ghcred

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了比赛-6月Round1相关的知识,希望对你有一定的参考价值。

A.饥饿的奶牛

想到线段覆盖问题的贪心解法,比如根据线段长度排序再选(据加藤惠实测能过 20% 数据),比如根据左端点为第一关键字,右端点为第二关键字排序再选……胡乱画图发现都不行。然后考虑 DP,f[i][j] 表示前 i 条线段选 j 条的最大收益,期望从 f[i-1][j-1] 和 f[i][j-1] 转移,发现不满足 DP 性质,因为子问题解不包含于当前问题解集中(最佳方式选 i-1 条后不一定能构造出选 i 条的最佳方案)。然后我想了下搜索……选一条线段之后,它包含的区间所在的线段不能再选,限制好像比较强,但是时间复杂度玄学……

正解: 对线段 [x, y] ,从 x 向 y+1 连一条权值为 y-x+1 的边。对每个点 i 向 i+1 连权值为 0 的边。设置一个源点,向所有点连权值为 0 的边。从源点开始进行最长路算法,答案是 max{ dis[i] }。

类似“何老板看守果园”,不过考试的时候并没有想到那道题。真的没想到 A 题这么难,太坑了OrzOrzOrz。

B.平衡的队列

正解: 以 x 坐标为关键字从小到大排序。讨论每个点,把种族 0 作为种族 -1 处理,这样可以让 1 和 -1 在累加中互相“消除”。设前缀和 sum[i] ,若 sum[x-1] = sum[y],则 [x, y] 是一段“平衡”的区间。对于所有 sum 值相同的位置,显然希望得到最右的位置 R[v] 和最左的位置 L[v],用 X 表示一点的 x 坐标,那么这样一组 L R 对答案的贡献是 X[R[v]] - X[L[v]+1] ,在所有合理的方案里取最大值就是最终答案。

C.颜色间距

正解: 对每个颜色,记录任意一个深度最深的节点 x ,max{ length(x, i) } 就是这个颜色的答案,其中 i 是这个颜色中不是 x 的其它点。求 length(a, b) ,可以找到 LCA(a, b) = c ,那么路径长度为 depth(a) + depth(b) - 2 * depth(c)

如果一个节点的子树中有和它相同颜色的节点,那么显然比起这个节点,它的子节点更适合作为一条路径的一端。所以期望一个节点没有相同颜色的节点在它的子树中,找到这个颜色深度最大的节点即可。

D.和谐数

正解: 用树状数组就非常好写。从左往右讨论每个值 A[i] ,L[i] 表示 i 左边更大的数的个数,L[i] = GetSum(INF)-GetSum(A[i]) 然后再 Modify(A[i], 1)。同理得到 R[i],然后算答案。注意离散化(排序)。

技术分享图片
 1 #include <stdio.h>
 2 #include <algorithm>
 3 #include <queue>
 4 #include <vector>
 5 
 6 using namespace std;
 7 
 8 const int INF = 1e9;
 9 const int _N = 2100;
10 
11 struct edge {
12     int v, w;
13     edge(int v = 0, int w = 0):
14         v(v), w(w) { }
15 };
16 
17 vector<edge> G[_N];
18 queue<int> Q;
19 int dis[_N];
20 bool mk[_N];
21 
22 void Ins(int t1, int t2, int t3) { G[t1].push_back(edge(t2, t3)); return; }
23 
24 void SPFA(int beg)
25 {
26     int i;
27     for (i = 0; i <= 2011; ++i)
28         dis[i] = -INF, mk[i] = false;
29     while (!Q.empty()) Q.pop();
30     dis[beg] = 0, Q.push(beg), mk[beg] = true;
31     while (!Q.empty()) {
32         int p = Q.front();
33         Q.pop(); mk[p] = false;
34         for (i = G[p].size()-1; i >= 0; --i) {
35             edge v = G[p][i];
36             if (dis[v.v] < dis[p] + v.w) {
37                 dis[v.v] = dis[p] + v.w;
38                 if (!mk[v.v]) Q.push(v.v), mk[v.v] = true;
39             }
40         }
41     }
42     return;
43 }
44 
45 int main()
46 {
47     int N, i;
48     scanf("%d", &N);
49     for (i = 1; i <= N; ++i) {
50         int t1, t2;
51         scanf("%d%d", &t1, &t2);
52         if (t1 > t2) swap(t1, t2);
53         Ins(t1, t2+1, t2+1-t1);
54     }
55     for (i = 1; i <= 2010; ++i) Ins(i, i+1, 0), Ins(0, i, 0);
56     SPFA(0);
57     int ans = 0;
58     for (i = 1; i <= 2011; ++i) ans = max(ans, dis[i]);
59     printf("%d
", ans);
60     return 0;
61 }
A
技术分享图片
 1 #include <stdio.h>
 2 #include <algorithm>
 3 #include <string.h>
 4 
 5 using namespace std;
 6 
 7 const int _N = 51000;
 8 const int INF = 1e9;
 9 
10 struct data {
11     int val, x;
12     bool operator < (const data &tmp) const
13     {
14         return x < tmp.x;
15     }
16 } A[_N];
17 
18 int L[_N*2], R[_N*2];
19 
20 int main()
21 {
22     int i, sum, mx_sum, mn_sum, ans, N;
23     scanf("%d", &N);
24     for (i = 1; i <= N; ++i) {
25         scanf("%d%d", &A[i].val, &A[i].x);
26         if (!A[i].val) A[i].val = -1;
27     }
28     sort(A+1, A+1+N);
29     
30     memset(L, -1, sizeof L), memset(R, -1, sizeof R);
31     sum = mx_sum = mn_sum = 0;
32     L[sum+_N] = R[sum+_N] = 0;
33     
34     for (i = 1; i <= N; ++i) {
35         mx_sum = max(mx_sum, sum += A[i].val);
36         mn_sum = min(mn_sum, sum);
37         if (L[sum+_N] == -1) L[sum+_N] = i;
38         R[sum+_N] = i;
39     }
40     ans = 0;
41     for (i = mn_sum; i <= mx_sum; ++i)
42         if (L[i+_N] != -1 && L[i+_N] < R[i+_N])
43             ans = max(ans, A[R[i+_N]].x-A[L[i+_N]+1].x);
44     printf("%d
", ans);
45     return 0;
46 }
B
技术分享图片
 1 #include <stdio.h>
 2 #include <algorithm>
 3 #include <vector>
 4 #include <math.h>
 5 
 6 using namespace std;
 7 
 8 const int _N = 200105;
 9 
10 vector<int> G[_N], P[_N];
11 int mxd, lg_mxd;
12 int depth[_N], X[_N], Clr[_N], dad[_N][20];
13 
14 void DFS(int node, int d)
15 {
16     mxd = max(mxd, depth[node] = d);
17     if (!X[Clr[node]] || depth[X[Clr[node]]] < depth[node])
18         X[Clr[node]] = node;
19     for (int i = G[node].size()-1; i >= 0; --i)
20         DFS(G[node][i], d+1);
21     return;
22 }
23 
24 int LCA(int x, int y)
25 {
26     if (depth[x] < depth[y]) swap(x, y);
27     int t = depth[x]-depth[y], i;
28     for (i = lg_mxd; i >= 0; --i)
29         if ((t>>i) & 1) x = dad[x][i];
30     if (x == y) return x;
31     for (i = lg_mxd; i >= 0; --i)
32         if (dad[x][i] != dad[y][i])
33             x = dad[x][i], y = dad[y][i];
34     return dad[x][0];
35 }
36 
37 int main()
38 {
39     int N, M, i, c, j, root;
40     scanf("%d%d", &N, &M);
41     for (i = 1; i <= N; ++i) {
42         scanf("%d%d", &Clr[i], &dad[i][0]);
43         P[Clr[i]].push_back(i);
44         if (!dad[i][0]) root = i;
45         else G[dad[i][0]].push_back(i);
46     }
47     DFS(root, 1);
48     lg_mxd = log2(mxd+0.5)+1;
49     for (j = 1; j <= lg_mxd; ++j)
50         for (i = 1; i <= N; ++i)
51             dad[i][j] = dad[dad[i][j-1]][j-1];
52     for (c = 1; c <= M; ++c) {
53         int ans = -1;
54         for (i = P[c].size()-1; i >= 0; --i)
55             if (P[c][i] != X[c])
56                 ans = max(ans, depth[X[c]]+depth[P[c][i]]-2-(depth[LCA(X[c], P[c][i])]-1)*2);
57         printf("%d
", ans);
58     }
59     return 0;
60 }
C
技术分享图片
 1 #include <stdio.h>
 2 #include <algorithm>
 3 #include <string.h>
 4 
 5 using namespace std;
 6 
 7 const int _N = 101005;
 8 
 9 struct data {
10     int val, id;
11 } A[_N];
12 
13 int cnt;
14 int B[_N], C[_N], L[_N], R[_N];
15 
16 bool val_first(data t1, data t2) { return t1.val < t2.val; }
17 
18 inline int lbt(int v) { return v & (-v); }
19 
20 int GetSum(int k)
21 {
22     int tmp = 0;
23     for (int i = k; i; i ^= lbt(i)) tmp += C[i];
24     return tmp;
25 }
26 
27 void Modify(int k, int d)
28 {
29     for (int i = k; i <= cnt; i += lbt(i)) C[i] += d;
30     return;
31 }
32 
33 int main()
34 {
35     int N, i;
36     scanf("%d", &N);
37     for (i = 1; i <= N; ++i)
38         scanf("%d", &A[i].val), A[i].id = i;
39     sort(A+1, A+1+N, val_first);
40     
41     B[A[1].id] = cnt = 1;
42     for (i = 2; i <= N; ++i)
43         B[A[i].id] = A[i].val == A[i-1].val ? B[A[i-1].id] : (++cnt);
44     for (i = 1; i <= N; ++i)
45         L[i] = GetSum(cnt)-GetSum(B[i]), Modify(B[i], 1);
46     memset(C, 0, sizeof C);
47     for (i = N; i >= 1; --i)
48         R[i] = GetSum(cnt)-GetSum(B[i]), Modify(B[i], 1);
49     int ans = 0;
50     for (i = 1; i <= N; ++i)
51         if (max(L[i], R[i]) > 2*min(L[i], R[i])) ++ans;
52     printf("%d
", ans);
53     return 0;
54 }
D

以上是关于比赛-6月Round1的主要内容,如果未能解决你的问题,请参考以下文章

体育比赛日程表,换对

2022年,ICPC比赛CCPC比赛CCF-CSP考试蓝桥杯比赛天梯赛日程

两个乒乓球队进行比赛,各出三人。甲队为a,b,c三人,乙队为x,y,z三人。 已抽签决定比赛名单。有人向队员打听比赛的名单。 a说他不和x比,c说他不和x,z比,请编程序找出三队赛手的名单。(代码片段

数学建模比赛日程

训练round1题解

2019年华南理工大学软件学院ACM集训队选拔赛 Round1