• 9.7


    标签(空格分隔): 解题报告

    ---

    ## 六校联考

    ---

    A

    给出 $n$ 个数 $a_i$,对于每个数求其他有多少数是该数的倍数
    $n <= 100000, a_i <= 1000000$

    Solve1:
    对于每个数枚举约数,那么对每个数答案的贡献就是约数出现的次数
    出现的次数可以预处理
    时间复杂度 $O(na_{i}^{frac{1}{2}})$

    Solve2:
    类似筛法
    对于每个数 $a_i$, 它只会对 $ka_i$ 的答案产生贡献
    当然只需要枚举所有不同的 $a_i$
    时间复杂度是调和级数也就是 $O(nlogn)$

    B

    给出长度为 $n$ 的字符串,最大化区间字母出现最多次数 - 字母出现最少次数,最少次数要不为 $0$

    对于任意两个字母 $a, b$,
    数组 $sum[a, i]$ 表示字母 $a$ 到 $i$ 的次数的前缀和
    答案可以表示成 $sum[a, i] - sum[a, j] - (sum[b, i] - sum[b, j])$
    等价于 $sum[a, i] - sum[b, i] - (sum[a, j] - sum[b, j])$
    记录 $sum[a, j] - sum[b, j]$ 的最小值
    防止出现空
    维护最大值和次大值
    时间复杂度 $O(26n)$

    C

    一张图,对于每个点 $t$, 删除掉从 $1$ 出发的到 $t$ 的最短路上的最后一条边后求到 $1$ 的最短路

    建出最短路树后同bzoj3694
    线段树维护树链剖分
    时间复杂度 $O(nlogn * logn)$

    D

    给出两个字符串 $a, b$, 允许 $k$ 次修改将任意串的任意字符修改为任意字符求最长连续相同子串
    长度 $300$

    由于连续,所以枚举从 $a, b$ 开始匹配的位置,每遇到不同就修改一次,此过程中取最大值

    时间复杂度 $O(n ^ 3)$

    E

    F

    ---

    ## nowcoder 提高组(第一场)

    ---

    A

    给定长度为 $n$ 序列 $a$,求长度 $>= len$ 的区间的最大中位数
    $n <= 1e5$

    二分答案 $x$, Check 当前序列中是否存在满足条件的中位数比 $x$ 大
    Check: 若 $a[i] >= x$, 则 $a[i] = 1$, 否则 $a[i] = -1$
    做前缀和
    这样处理出来之后,若一段区间的和为正数,则说明存在更优的中位数

    #include <bits/stdc++.h>
     
    using namespace std;
     
    const int maxn = 100005;
     
    int a[maxn], n, L;
     
    bool test(int z)
    {
        static int b[maxn];
        for(int i = 1;i <= n;i ++)
            if (a[i] >= z) b[i] = 1; else b[i] = -1;
        for(int i = 1, mi = (1 << 30);i <= n;i ++)
        {
            if (i >= L) mi = min(mi, b[i - L]);
            b[i] += b[i - 1];
            if (i >= L && b[i] - mi > 0) return 1;
        }
        return 0;
    }
     
    int main()
    {
        scanf("%d%d", &n, &L);
        for(int i = 1;i <= n;i ++) scanf("%d", &a[i]);
        int l = 0, r = int(1e9), tmp;
        for(int mid;l <= r;)
        {
            mid = l + r >> 1;
            if (test(mid)) tmp = mid, l = mid + 1; else r = mid - 1;
        }
        printf("%d
    ", tmp);
        return 0;
    }
    View Code

    B

    数位 dp

    C

    一棵树,存在 $m$ 条覆盖路径覆盖这棵树,对于每个点 $x$, 求出深度最小的点 $y$ 使得 $x -> y$ 这段路径被至少 $k$ 条覆盖路径完全覆盖,注意是完全覆盖。

    由于是完全覆盖,所以这 $k$ 条路径都经过了 $x -> y$ 这条链
    问题转化:树上存在某些点可以向上跳,查询相当于查询 $x$ 的子树中的所有向上跳的高度的 $k$ 的值
    主席树 + dfs序

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <string>
    #include <vector>
     
    using namespace std;
     
    const int N = 2e5 + 10;
     
    #define LL long long
    #define gc getchar()
     
    inline int read() {
        int x = 0; char c = gc;
        while(c < '0' || c > '9') c = gc;
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = gc;
        return x;
    }
     
    struct Node_1{
        int u, v, nxt;
    }G[N << 2];
    int topp[N], fa[N], size[N], son[N], deep[N], tree[N], bef[N], data[N], Tree, lst[N], rst[N];
    int now, head[N];
    int n, m;
    int X[N], Y[N], lca[N];
    int Root[N];
     
    void Add(int u, int v) {G[++ now].v = v; G[now].nxt = head[u]; head[u] = now;}
     
    void Dfs_1(int u, int f_, int dep) {
        fa[u] = f_, deep[u] = dep, size[u] = 1;
        for(int i = head[u]; ~ i; i = G[i].nxt) {
            int v = G[i].v;
            if(v == f_) continue;
            Dfs_1(v, u, dep + 1);
            size[u] += size[v];
            if(size[son[u]] < size[v]) son[u] = v;
        }
    }
     
    void Dfs_2(int u, int tp) {
        topp[u] = tp, tree[u] = ++ Tree, lst[u] = Tree, bef[Tree] = u;;
        if(!son[u]) {rst[u] = Tree; return ;}
        Dfs_2(son[u], tp);
        for(int i = head[u]; ~ i; i = G[i].nxt) {
            int v = G[i].v;
            if(v != fa[u] && v != son[u]) Dfs_2(v, v);
        }
        rst[u] = Tree;
    }
     
    inline int Lca(int x, int y) {
        int tpx = topp[x], tpy = topp[y];
        while(tpx != tpy){
            if(deep[tpx] < deep[tpy]) swap(x, y), swap(tpx, tpy);
            x = fa[tpx], tpx = topp[x];
        }
        return deep[x] < deep[y] ? x : y;
    }
     
    int Lson[N * 65], Rson[N * 65], W[N * 65];
     
    void Fill(int x, int y) {
        Lson[x] = Lson[y], Rson[x] = Rson[y], W[x] = W[y];
    }
     
    int Segjs;
     
    void Insert(int &rt, int l, int r, int x) {
        Fill(++ Segjs, rt);
        rt = Segjs;
        W[rt] ++;
        if(l == r) return ;
        int mid = (l + r) >> 1;
        if(x <= mid) Insert(Lson[rt], l, mid, x);
        else Insert(Rson[rt], mid + 1, r, x);
    }
     
    int Seg(int lrt, int rrt, int l, int r, int k) {
        if(l == r) {
            if(k > (W[rrt] - W[lrt])) return (1 << 30);
            return l;
        }
        int ll = Lson[lrt], rr = Lson[rrt];
        int num = W[Lson[rrt]] - W[Lson[lrt]];
        int mid = (l + r) >> 1;
        if(num >= k) return Seg(Lson[lrt], Lson[rrt], l, mid, k);
        else return Seg(Rson[lrt], Rson[rrt], mid + 1, r, k - num);
    }
     
    int b;
    vector <int> Data[N];
     
    int main() {
        n = read(), m = read();
        for(int i = 1; i <= n; i ++) head[i] = -1;
        for(int i = 1; i < n; i ++) {
            int u = read(), v = read();
            Add(u, v), Add(v, u);
        }
        Dfs_1(1, 0, 1);
        Dfs_2(1, 1);
        for(int i = 1; i <= m; i ++) {
            X[i] = read(), Y[i] = read();
            lca[i] = Lca(X[i], Y[i]);
        }
        for(int i = 1; i <= m; i ++) {
            Data[X[i]].push_back(deep[lca[i]]);
            Data[Y[i]].push_back(deep[lca[i]]);
        }
        for(int i = 1; i <= n; i ++) {
            Root[i] = Root[i - 1];
            b = bef[i];
            int S = Data[b].size();
            if(S == 0) continue;
            for(int j = 0; j < S; j ++) {
                int x = Data[b][j];
                Insert(Root[i], 1, n, x);
            }
        }
        int q = read();
        for(int i = 1; i <= q; i ++) {
            int x = read(), k = read();
            int a = Seg(Root[lst[x] - 1], Root[rst[x]], 1, n, k);
            if(a >= deep[x]) printf("0
    ");
            else printf("%d
    ", deep[x] - a);
        }
        return 0;
    }
    View Code

    ---

    ## zhengruioj Day3

    ---

    T1

    给出长度 $<= n$ 的数组 $a$, $a_i != a_j, a_i <= n$
    求长度为 $n$ 的排列使得数组 $a$ 的元素相对位置不变,最小化排列的字典序。

    从 $1$ 开始枚举不在 $a$ 中的数,每次与 $a$ 数组的尾元素比较,输出较小的数并且删除 $a$ 的尾元素

    T2

    采矿点升序排序, $a_i$ 表示第 $i$ 个采矿点能采到的矿石种类数,$b_i$ 表示第 $i$ 个采矿点第一次能采到的矿石种类数。显然 $ans = sum_{i = 1} ^ {m} 2 ^ {b_i} * 2 ^ {a_i - b_i}$

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <cstring>
    #include <string>
    
    using namespace std;
    const int N = 1e5 + 10;
    
    int A[N], B[N], Use[N];
    struct Node {int L, R;} C[N];
    int n, m;
    
    #define LL long long
    
    const int Mod = 998244353;
    
    inline LL Ksm(LL a, LL b) {
        LL ret = 1;
        while(b) {
            if(b & 1) ret = ret * a % Mod;
            a = a * a % Mod;
            b >>= 1;
        }
        return ret;
    }
    
    int main() {
        cin >> n >> m;
        for(int i = 1; i <= n; i ++) cin >> C[i].L >> C[i].R;
        for(int i = 1; i <= m; i ++) cin >> Use[i];
        sort(Use + 1, Use + m + 1);
        for(int i = 1; i <= n; i ++) {
            int Wei1 = lower_bound(Use + 1, Use + m + 1, C[i].L) - Use;
            int Wei2 = lower_bound(Use + 1, Use + m + 1, C[i].R) - Use;
            if(C[i].R < Use[1] || C[i].L > Use[m]) continue;
            if(Wei1 == Wei2 && Use[Wei2] > C[i].R) continue;
            if((Use[Wei2] > C[i].R) || (Wei2 > m)) Wei2 --;
            A[Wei1] ++, A[Wei2 + 1] --;
            B[Wei1] ++;
        }
        for(int i = 1; i <= m; i ++) A[i] += A[i - 1];
        LL Answer = 0;
        for(int i = 1; i <= m; i ++)
            if(B[i]) (Answer += ((Ksm((LL)2, (LL)B[i]) - 1) * Ksm((LL)2, (LL)A[i] - (LL)B[i])) % Mod) %= Mod;
        cout << Answer;
        return 0;
    }
    View Code

    T3

  • 相关阅读:
    个人博客05
    个人随笔04
    ELK-Kibana汉化
    Centos7下使用mail发送邮件
    使用Docker搭建Tomcat运行环境
    Jenkins添加maven插件
    linux下安装nodejs及npm
    服务器重启后Jenkins项目部分丢失问题解决方法
    【linux】如何查看文件的创建、修改时间
    禅道
  • 原文地址:https://www.cnblogs.com/shandongs1/p/9627792.html
Copyright © 2020-2023  润新知