zoukankan      html  css  js  c++  java
  • Educational Codeforces Round 7 部分题解

    C. Not Equal on a Segment

    脑子转不动,结果想了半天才做出来。。

    有一个性质:(a geq b)(a leq b Leftrightarrow a = b)

    所以我们需要维护一个区间最小值 (mathrm{minn}) 和区间最大值 (mathrm{maxn}),如果 (mathrm{minn} = mathrm{maxn} = x) 即是无解。

    这题还让我们随便输出一个不等于 (x) 的数的位置,既然 (mathrm{maxn}, mathrm{minn}) 至少有一个不等于 (x),那我们只需要输出那个数的位置就好了。

    做法也很简单,使用线段树维护四个信息:区间最大值、最小值和区间最大值、最小值所在的位置。挺好写的。

    时间复杂度 (O(n log n))

    const int MAXN = 2e5 + 10;
    
    int n, m;
    int aa[MAXN];
    
    namespace Segt {
        struct Node {
            int minn, maxn;
            int minp, maxp;
            Node() {minn = maxn = minp = maxp = 0;}
        } segt[MAXN << 2];
    
        #define ls (p << 1)
        #define rs (p << 1 | 1)
    
        Node Merge(Node pl, Node pr) {
            Node ret;
            if (pl.minn < pr.minn) { ret.minn = pl.minn; ret.minp = pl.minp; } 
            else { ret.minn = pr.minn; ret.minp = pr.minp; }
            if (pl.maxn > pr.maxn) { ret.maxn = pl.maxn; ret.maxp = pl.maxp; } 
            else { ret.maxn = pr.maxn; ret.maxp = pr.maxp; }
            return ret;
        }
        void Update(int p) {
            segt[p] = Merge(segt[ls], segt[rs]);
        }
        void buildTree(int p, int l, int r, int *aa) {
            if (l == r) {
                segt[p].minn = segt[p].maxn = aa[l];
                segt[p].minp = segt[p].maxp = l;
                return;
            } int mid = (l + r) >> 1;
            buildTree(ls, l, mid, aa); buildTree(rs, mid + 1, r, aa);
            Update(p);
        }
        Node Query(int p, int l, int r, int ll, int rr) {
            if (l == ll && rr == r) return segt[p];
            int mid = (l + r) >> 1;
            if (rr <= mid) return Query(ls, l, mid, ll, rr);
            else if (mid + 1 <= ll) return Query(rs, mid + 1, r, ll, rr);
            else return Merge(Query(ls, l, mid, ll, mid), Query(rs, mid + 1, r, mid + 1, rr));
        }
    }
    
    int main() {
        std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
        cin >> n >> m;
        rep (i, 1, n) cin >> aa[i];
        Segt::buildTree(1, 1, n, aa);
        rep (i, 1, m) {
            int l, r, x; cin >> l >> r >> x;
            Segt::Node res = Segt::Query(1, 1, n, l, r);
            if (res.minn == x && res.maxn == x) puts("-1");
            else {
                if (res.minn == x) printf("%d
    ", res.maxp);
                else printf("%d
    ", res.minp);
            }
        }
        return 0;
    }
    

    实际上还有一种更简单的做法:求出每个位置往前走,第一个和它不同的数字在哪,然后先看右端点是不是和 x 相同,再看右端点往前走第一个和它不同的数字在不在左端点范围里。

    const int MAXN = 2e5 + 10;
    
    int n, m;
    int aa[MAXN];
    int prev[MAXN];
    
    int main() {
        std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
        n = read(); m = read();
        rep (i, 1, n) {
            aa[i] = read();
            if (aa[i] == aa[i - 1]) prev[i] = prev[i - 1];
            else prev[i] = i - 1;
        }
        rep (i, 1, m) {
            int l = read(); int r = read(); int x = read();
            if (aa[r] != x) printf("%d
    ", r);
            else if (prev[r] >= l) printf("%d
    ", prev[r]);
            else puts("-1");
        }
        return 0;
    }
    

    D. Optimal Number Permutation

    有趣的构造题。

    考虑能不能把这个式子构造出 0,这种情况即是:(forall i in [1, n - 1], d_i = n - i),并且 (d_n) 可以是任意值。

    例如 (n = 6) 时:

    d1 = 5
    d2 = 4
    d3 = 3
    d4 = 2
    d5 = 1
    

    接下来就胡乱手玩碰运气,尝试从小到大安排、从大到小安排,从前往后填、循环填……可以发现从小到大安排,循环找空填是一种似乎靠谱的构造方式:

    1 3 5 5 3 1 2 4 6 4 2 6
    

    (1)(n - 1),依次找第一个能放得下当前数字的位置填进去。可以发现这样的数字结构是两段回文数字拼起来,而且最后一定会剩下两个空,放入 (n) 即可。

    const int MAXN = 5e5 + 10;
    
    int n;
    int ans[MAXN << 1];
    
    void Solve() {
        int lenl = n, lenr = n - 1;
        int stl = 1, str = stl + lenl;
        int edl = stl + lenl - 1, edr = str + lenr - 1;
        for (int i = 1; i <= n - 1; i += 2) {
            int pos = (i + 1) >> 1;
            int ul = stl + pos - 1;
            int ur = edl - ul + 1;
            ans[ul] = ans[ur] = i;
        }
        for (int i = 2; i <= n - 1; i += 2) {
            int pos = i >> 1;
            int ul = str + pos - 1;
            int ur = edr - pos + 1;
            ans[ul] = ans[ur] = i;
        }
        for (int i = 1; i <= (n << 1); ++i) if (!ans[i]) ans[i] = n;
    }
    
    int main() {
        std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
        cin >> n;
        Solve(); // both compatible with odd and even
        rep (i, 1, (n << 1)) printf("%d ", ans[i]);
        puts("");
        return 0;
    }
    

    E. Ants in Leaves

    很经典的题了。考虑贪心,对于所有根的儿子求出所有蚂蚁离开这个子树的最短时间,答案即是这些时间取 max。

    怎么求每棵子树的最短时间?

    考虑如果没有深度相同的点,那么答案就是最大深度,但是如果有了相同深度的点,这些相同深度的点就需要排队,所以不妨按顺序将它们的深度手动加一,深度加一就代表这个点需要多排一秒的队。这么一波处理完之后,答案即是最大深度。

    const int MAXN = 5e5 + 10;
    
    int n; std::vector<int> G[MAXN];
    
    std::vector<int> depths;
    
    void dfs(int u, int fa, int dep) {
        if (G[u].size() == 1) depths.push_back(dep);
        forall (G[u], i) {
            int v = G[u][i];
            if (v == fa) continue;
            dfs(v, u, dep + 1);
        }
    }
    
    int main() {
        std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
        n = read();
        rep (i, 1, n - 1) {
            int u = read(); int v = read();
            G[u].push_back(v); G[v].push_back(u);
        }
        int ans = 0;
        forall (G[1], i) {
            int v = G[1][i];
            depths.clear();
            dfs(v, 1, 1);
            std::sort(ALL(depths));
            for (int i = 1; i < (int) depths.size(); ++i) {
                depths[i] = std::max(depths[i], depths[i - 1] + 1);
            }
            ans = std::max(ans, depths[depths.size() - 1]);
        } printf("%d
    ", ans);
        return 0;
    }
    

    F

    数学题……

  • 相关阅读:
    Docker搭建持续集成平台Jenkins
    Selenium Webdriver 架构
    JMeter性能监控系统:Jmeter + InfluxDB + Grafana
    持续集成平台Jenkins配置方法介绍
    perl中的map
    Smarty 配置文件中的相对路径
    挑出IIS日志里某一文件的请求次数
    写PHP,内伤中....
    File::Find
    强制删除删除不了的文件
  • 原文地址:https://www.cnblogs.com/handwer/p/15467734.html
Copyright © 2011-2022 走看看