zoukankan      html  css  js  c++  java
  • [bzoj4240]有趣的家庭菜园_树状数组

    有趣的家庭菜园

    题目链接https://lydsy.com/JudgeOnline/problem.php?id=4240

    数据范围:略。


    题解

    第一步比较简单,只需要排序之后,每个数不是在左边就是在右边。

    我们只需要计算出,当前这个数如果在左边,能跟没放进数列的数构成的逆序对数和在右边哪个更小。

    这个过程可以用树状数组维护。

    代码

    #include <bits/stdc++.h>
    
    #define N 1000010 
    
    using namespace std;
    
    typedef long long ll;
    
    char *p1, *p2, buf[100000];
    
    #define nc() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1 ++ )
    
    int rd() {
    	int x = 0, f = 1;
    	char c = nc();
    	while (c < 48) {
    		if (c == '-')
    			f = -1;
    		c = nc();
    	}
    	while (c > 47) {
    		x = (((x << 2) + x) << 1) + (c ^ 48), c = nc();
    	}
    	return x * f;
    }
    
    int tr[N];
    
    inline int lowbit(int x) {
    	return x & (-x);
    }
    
    void upd(int x, int val) {
    	for (int i = x; i < N; i += lowbit(i)) {
    		tr[i] += val;
    	}
    }
    
    int qry(int x) {
    	int ans = 0;
    	for (int i = x; i; i -= lowbit(i)) {
    		ans += tr[i];
    	}
    	return ans;
    }
    
    struct Node {
    	int val, id;
    }a[N];
    
    inline bool cmp(const Node &a, const Node &b) {
    	return a.val > b.val;
    }
    
    int main() {
    	int n = rd();
    	for (int i = 1; i <= n; i ++ ) {
    		a[i].val = rd(), a[i].id = i;
    	}
    	ll ans = 0;
    	sort(a + 1, a + n + 1, cmp);
    	for (int i = 1; i <= n; ){
    		int j;
    		for (j = i; j <= n; j ++ ) {
    			int mdl = qry(a[j].id);
    			ans += min(mdl, i - 1 - mdl);
    			if (a[j + 1].val != a[j].val) {
    				break;
    			}
    		}
    		for (; i <= j; i ++ ) {
    			upd(a[i].id, 1);
    		}
    	}
    
    	cout << ans << endl ;
    	return 0;
    }
    
  • 相关阅读:
    Java集合
    C#高级应用
    使用C#分层查询多个表数据
    数据库之SQL语句查询基础
    简要介绍一下MD5加密的书写
    C#简单工厂模式和单列设计模式潜要解析
    Struts2测试题
    小程序自定义组件
    flex布局笔记
    小程序的双线程模型
  • 原文地址:https://www.cnblogs.com/ShuraK/p/11773422.html
Copyright © 2011-2022 走看看