zoukankan      html  css  js  c++  java
  • [POI2011]ROT-Tree Rotations

    题目:传送门

    题解:对每个叶子建立一颗线段树,从底向上合并两个儿子。以节点 u 为根的子树的逆序对 = 以 lson[ u ] 为根的子树的逆序对 + 以 rson[ u ] 为根的子树的逆序对 + 跨过 lson[ u ] 和 rson[ u ] 的逆序对。

    const int N = 200005;
    
    LL ansl, ansr, ans;
    
    int n, cnt, tot;
    int v[2 * N], l[2 * N], r[2 * N], ls[20 * N], rs[20 * N], root[20 * N], sum[20 * N];
    
    void readTree(int x) {
        sc(v[x]);
        if (!v[x]) {
            l[x] = ++cnt;
            readTree(l[x]);
            r[x] = ++cnt;
            readTree(r[x]);
        }
    }
    
    void Pushup(int rt) {
        sum[rt] = sum[ls[rt]] + sum[rs[rt]];
    }
    
    void Build(int l, int r, int &rt, int pos) {
        if (!rt) rt = ++tot;
        if (l == r) {
            sum[rt] = 1;
            return;
        }
        int mid = (l + r) >> 1;
        if (pos <= mid) Build(l, mid, ls[rt], pos);
        else Build(mid + 1, r, rs[rt], pos);
        Pushup(rt);
    }
    
    int Merge(int x, int y) {
        if (!x || !y) return x ^ y;
        ansl += 1ll * sum[ls[x]] * sum[rs[y]];
        ansr += 1ll * sum[rs[x]] * sum[ls[y]];
        ls[x] = Merge(ls[x], ls[y]);
        rs[x] = Merge(rs[x], rs[y]);
        Pushup(x);
        return x;
    }
    
    void DFS(int x = 1) {
        if (!x) return;
        DFS(l[x]);
        DFS(r[x]);
        if (!v[x]) {
            ansl = ansr = 0;
            root[x] = Merge(root[l[x]], root[r[x]]);
            ans += min(ansl, ansr);
        }
    }
    
    int main()
    {
        sc(n);
        cnt++;
        readTree(1);
        Rep(i, 1, cnt) if (v[i]) Build(1, n, root[i], v[i]);
        DFS(1);
        printf("%lld
    ", ans);
    }
  • 相关阅读:
    angular2 UT 导入 jquery问题解决
    css超过指定宽度用...表示
    karma-coverage通过浏览器显示
    angular2复选框及其按钮
    前端分页控制
    input复选框checkbox默认样式纯css修改
    弧形侧边栏
    浅谈软件测试
    随笔1
    java注解小记
  • 原文地址:https://www.cnblogs.com/zgglj-com/p/9549815.html
Copyright © 2011-2022 走看看