• 2212: [Poi2011]Tree Rotations


    2212: [Poi2011]Tree Rotations

    https://www.lydsy.com/JudgeOnline/problem.php?id=2212

    分析:

      线段树合并。

      首先对每个节点建立一棵权值线段树,然后遍历整棵树,从叶子节点开始合并,每次合并两个节点的主席树,判断是否交换这两个节点,求出这两个节点分在前面所形成的逆序对。

      求逆序对:对于主席树中的右子树一定比左子树大,所以每次合并一个节点时,直接用右子树的个数乘以左子树的个数,不断递归。

    代码:

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<cmath>
     5 #include<iostream>
     6 #include<cctype>
     7 #include<set>
     8 #include<vector>
     9 #include<queue>
    10 #include<map>
    11 #define fi(s) freopen(s,"r",stdin);
    12 #define fo(s) freopen(s,"w",stdout);
    13 using namespace std;
    14 typedef long long LL;
    15 
    16 inline int read() {
    17     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
    18     for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
    19 }
    20 
    21 const int N = 200005;
    22 
    23 int A[N << 1], T[N << 1][2], Root[N << 1], sum[N * 20], ls[N * 20], rs[N * 20];
    24 int Index, tot, Rt;
    25 LL Ans, Ans0, Ans1;
    26 
    27 void ReadTree(int &x) {
    28     x = ++Index;
    29     A[x] = read();
    30     if (A[x]) return ;
    31     ReadTree(T[x][0]); 
    32     ReadTree(T[x][1]);
    33 }
    34 
    35 void Insert(int l,int r,int &rt,int p) {
    36     rt = ++tot;
    37     sum[rt] = 1;
    38     if (l == r) return ;
    39     int mid = (l + r) >> 1;
    40     if (p <= mid) Insert(l, mid, ls[rt], p);
    41     else Insert(mid + 1, r, rs[rt], p);
    42 }
    43 
    44 int Merge(int x,int y) { // 合并x y 
    45     if (!x || !y) return x + y;
    46     Ans0 += 1ll * sum[rs[x]] * sum[ls[y]]; // x在前 
    47     Ans1 += 1ll * sum[rs[y]] * sum[ls[x]]; // y在前 
    48     ls[x] = Merge(ls[x], ls[y]);
    49     rs[x] = Merge(rs[x], rs[y]);
    50     sum[x] += sum[y];
    51     return x;
    52 }
    53 
    54 void solve(int x) {
    55     if (A[x]) return ;
    56     solve(T[x][0]); solve(T[x][1]);
    57     Ans0 = 0, Ans1 = 0;
    58     Root[x] = Merge(Root[T[x][0]], Root[T[x][1]]);
    59     Ans += min(Ans0, Ans1);    
    60 }
    61 
    62 int main() {
    63     
    64     int n = read();
    65     ReadTree(Rt);
    66     for (int i=1; i<=Index; ++i) 
    67         if (A[i]) Insert(1, n, Root[i], A[i]);
    68     solve(Rt);
    69     cout << Ans << endl;
    70     return 0;
    71 }
  • 相关阅读:
    一个封装好的使用完成端口的socket通讯类
    IOCP编程注意事项
    判断socket是否连接(windows socket)
    CRITICAL_SECTION同步易出错的地方
    OCP-1Z0-053-V13.02-43题
    OCP-1Z0-053-V13.02-24题
    OCP-1Z0-053-V13.02-490题
    OCP-1Z0-053-V12.02-456题
    OCP-1Z0-053-V12.02-447题
    OCP-1Z0-053-V13.02-710题
  • 原文地址:https://www.cnblogs.com/mjtcn/p/9713441.html
Copyright © 2020-2023  润新知