zoukankan      html  css  js  c++  java
  • 比赛-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
  • 相关阅读:
    JavaScript 垃圾回收
    JavaScript 跳坑指南
    javaScript AJAX
    高效 JavaScript
    Java使用 Thumbnails 压缩图片
    Vue前端压缩图片
    JS input输入框字数超出长度显示省略号.....
    Vue图片浏览组件vviewer使用
    浏览器获取京东cookie
    图片在容器内水平垂直居中显示
  • 原文地址:https://www.cnblogs.com/ghcred/p/9184483.html
Copyright © 2011-2022 走看看