zoukankan      html  css  js  c++  java
  • 「题解」LgP3521 [POI2011]ROT-Tree Rotations

    注意到如果我们用类似 cdq 分治的思想,对于每个节点统计“左子树的叶子和右子树的叶子进行匹配的逆序对数”从而求和得到总体逆序对数,那么对于任意两个不同节点,他们各自的两个子树交不交换位置对答案的影响是互相独立的。

    所以只需要求对于每个节点是否交换优即可。

    考虑在每个叶节点开权值线段树然后向上合并,合并的过程中我们就能以同样类似 cdq 分治思想的做法,把 逆序对/顺序对 求出来,取最小值加入到答案中即可。

    具体求法是,线段树合并的从中间断开递归的时候,算出左区间和右区间匹配出的逆序对,然后再递归下去的时候算左区间和右区间内部的逆序对。

    时间复杂度 (mathcal{O}(nlog n))

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    typedef long long ll;
    template <typename T> T Max(T x, T y) { return x > y ? x : y; }
    template <typename T> T Min(T x, T y) { return x < y ? x : y; }
    template <typename T>
    T &read(T &r) {
    	r = 0; bool w = 0; char ch = getchar();
    	while(ch < '0' || ch > '9') w = ch == '-' ? 1 : 0, ch = getchar();
    	while(ch >= '0' && ch <= '9') r = (r << 3) + (r <<1) + (ch ^ 48), ch = getchar();
    	return r = w ? -r : r;
    }
    #define ls(x) tree[x].lson
    #define rs(x) tree[x].rson
    const int N = 3.8e6;
    const int INF = 0x7fffffff;
    int n, trnt;
    struct SGT {
    	int lson, rson, sum;
    }tree[N];
    void modify(int &x, int tl, int tr, int pos) {
    	if(!x)
    		x = ++trnt;
    	++tree[x].sum;
    	if(tl == tr) return ;
    	int mid = (tl + tr) >> 1;
    	if(pos <= mid) modify(ls(x), tl, mid, pos);
    	else modify(rs(x), mid+1, tr, pos);
    }
    ll s1, s2, ans;
    void merge(int &x, int y, int tl, int tr) {
    	if(!x || !y) {
    		x = x + y;
    		return ;
    	}
    	tree[x].sum += tree[y].sum;
    	if(tl == tr) return ;
    	s1 += 1ll * tree[rs(x)].sum * tree[ls(y)].sum;
    	s2 += 1ll * tree[rs(y)].sum * tree[ls(x)].sum;
    	int mid = (tl + tr) >> 1;
    	merge(ls(x), ls(y), tl, mid);
    	merge(rs(x), rs(y), mid+1, tr);
    }
    void dfs(int &x) {
    	int t; read(t);
    	if(!t) {
    		int lson = 0, rson = 0;
    		dfs(lson);
    		dfs(rson);
    		s1 = 0; s2 = 0;
    		x = lson; merge(x, rson, 1, n);
    		ans += Min(s1, s2);
    	}
    	else modify(x, 1, n, t);
    }
    #undef ls
    #undef rs
    signed main() {
    //	freopen("in.txt", "r", stdin);
    	read(n); int root = 0;
    	dfs(root);
    	printf("%lld
    ", ans);
    	return 0;
    }
    
  • 相关阅读:
    Unix domain sockets
    python异常处理
    php注册登录源代码
    div,css命名规范!
    html、css和js注释的规范用法
    PHPstrom的Disable Power Save Mode
    开通了博客园
    O(1)时间删除链表中的节点 13
    打印1到最大的n位数 12
    自己实现一个数的整数次方 11
  • 原文地址:https://www.cnblogs.com/do-while-true/p/14955985.html
Copyright © 2011-2022 走看看