• 2017博普杯 东北大学邀请赛(B. Drink too much water)(贪心+树链剖分)


     题目地址:https://oj.neu.edu.cn/problem/1204

    题目大意:

    其实就是树上的线段覆盖,

    给出一棵n个结点的树,然后给出树上的一些路径进行覆盖,然后要求选取最少的点,能够把这些线段都占有

    (或者说:一开始树上每个结点权值都为0,选取最少的点,把它们的权重变成1,使得询问的每一条路径上有含有权值为1的结点)

    题解:

    类似线段覆盖(线段覆盖是按照右端点贪心)

    这个题就是按照每个路径的lca的深度贪心

    也就是说把询问按照lca的深度从大到小排序

    然后依次枚举询问

    如果当前询问的路径没有权值为1的结点,就把lca赋值成1,答案加1

    如果有就跳过

    最后输出就可以了

    整个过程用树链剖分就可以维护

    (第一次wa是没有多组输入输出,第二次wa是把return 0 放在多组数据里了,第三次wa是忘记删freopen。。。orz)

    #include <algorithm>
    #include <cstring>
    #include <iostream>
    #include <cstdio>
    #include <vector>
    using namespace std;
    const int maxn = 1e5 + 100;
    const int maxm = 5e5 + 100;
    int tree[maxn*4], deep[maxn], p[maxn], sz[maxn], son[maxn], top[maxn], F[maxn];
    int tot = 0;
    vector<int> G[maxn];
    struct Que{
        int x, y, lca;
        bool operator <(const Que& B) const{
            return deep[lca] < deep[B.lca];
        }
    };
    vector<Que> Q;
    void Insert(int o, int l, int r, int k, int v){
        if(l == r) { tree[o] = v; return; }
        int mid = (l+r)>>1;
        if(k <= mid) Insert(o*2, l, mid, k, v);
        else Insert(o*2+1, mid+1, r, k, v);
        tree[o] = max(tree[o*2], tree[o*2+1]);
    }
    int Query(int o, int l, int r, int L, int R){
        if(L <= l && r <= R) return tree[o];
        int mid = (l+r)>>1, ans = 0;
        if(L <= mid) ans = max(ans, Query(o*2, l, mid, L, R));
        if(R > mid) ans = max(ans, Query(o*2+1, mid+1, r, L, R));
        return ans;
    }
    
    int dfs1(int x, int fa, int d){
        deep[x] = d;
        p[x] = fa;
        sz[x] = 1;
        for(auto to : G[x]){
            if(fa == to) continue;
            sz[x] += dfs1(to, x, d+1);
            if(sz[to] > sz[son[x]]) son[x] = to;
        }
        return sz[x];
    }
    void dfs2(int x, int fa){
        F[x] = ++tot;
        if(son[fa] == x) top[x] = top[fa];
        else top[x] = x;
        if(son[x]) dfs2(son[x], x);
        for(auto to : G[x]){
            if(to == fa || to == son[x]) continue;
            dfs2(to, x);
        }
    }
    int TQuery(int x, int y, int &lca){
        int ans = 0;
        while(top[x] != top[y]){
            if(deep[top[y]] > deep[top[x]]) swap(x, y);
            ans = max(ans, Query(1, 1, tot, F[top[x]], F[x]));
            x = p[top[x]];
        }
        if(deep[x] > deep[y]) swap(x, y);
        ans = max(ans, Query(1, 1, tot, F[x], F[y]));
        lca = x;
        return ans;
    }
    
    int main()
    {
    
        int n, m, x, y;
        while(cin>>n){
            tot = 0;
            for(int i = 0; i <= n; i++) G[i].clear();
            memset(son, 0, sizeof(son));
            memset(tree, 0, sizeof(tree));
            for(int i = 1; i <= n; i++){
                scanf("%d %d", &x, &y);
                G[x].push_back(y);
                G[y].push_back(x);
            }
            dfs1(0, 0, 1);
            dfs2(0, 0);
            cin>>m;
            Q.resize(m);
            for(int i = 0; i < m; i++){
                scanf("%d %d", &Q[i].x, &Q[i].y);
                TQuery(Q[i].x, Q[i].y, Q[i].lca);
            }
            sort(Q.begin(), Q.end());
            reverse(Q.begin(), Q.end());
            int ans = 0;
            for(auto a : Q){
                int k = TQuery(a.x, a.y, a.lca);
                if(k) continue;
                else Insert(1, 1, tot, F[a.lca], 1), ans++;
            }
            cout<<ans<<endl;
        }
        return 0;
    }
  • 相关阅读:
    Kubernetes Declarative Deployment
    Kubernetes集群如何查看scheduler/controller manager谁是leader
    kubelet 配置管理 (一)
    Kubernetes Ingress
    如何计算Kubernetes容器CPU使用率
    Kubernetes概念
    .NET陷阱之四:事件监听带来的问题与弱监听器
    .NET陷阱之三:“正确”使用控件也会造成内存泄露
    .NET陷阱之五:奇怪的OutOfMemoryException——大对象堆引起的问题与对策
    自己编译得到 arm64v8a 版本的libZBarDecoder.SO文件
  • 原文地址:https://www.cnblogs.com/Saurus/p/7240036.html
Copyright © 2020-2023  润新知