hdu 1394 线段树求逆序对

来源:互联网 发布:万网域名转移godaddy 编辑:程序博客网 时间:2024/06/02 03:00

HDU 1394




数据略水, 并且, 建树函数都没必要用了, 暴力也能过(学长说的), 一颗赛艇。


题解:找初始逆序对, 然后, 没往后移一位的逆序对数变化为,增加n - a[i], 减少 a[i] - 1,(a[i]自增处理过的);

   找初始逆序对, 就找 {a[i] + 1, n}区间内出现的个数,没输入一个都处理;


AC code:

//lrl's submission#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define debug 0#define mid ((l + r) >> 1)#define ls  rt << 1, l, mid#define rs  rt << 1 | 1, mid + 1, r#define M(a, b) memset(a, b, sizeof(a))const int maxn = 5000 + 5;int sum[maxn << 2], n, a[maxn];void pushUp(int rt){sum[rt] = sum[rt << 1] + sum[rt << 1|1];}void update(int a, int rt, int l, int r){if(a < l || a > r)return;if(l == r){sum[rt]++;return;}update(a, ls);update(a, rs);pushUp(rt);}int query(int ql, int qr, int rt, int l, int r){if(ql <=l && qr >= r)return sum[rt];int ans = 0;if(ql <= mid)ans += query(ql, qr, ls);if(qr > mid)ans += query(ql, qr, rs);return ans;}int main(){#if debug    freopen("in.txt", "r", stdin);#endif // debug    while(~scanf("%d", &n))    {        M(sum, 0);       // build();       int s = 0, mn;        for(int i = 1; i <= n; i++){scanf("%d", &a[i]);a[i]++;s += query(a[i] + 1, n, 1, 1, n);update(a[i], 1, 1, n);}mn = s;for(int i = 1; i < n; i++){mn -= a[i] - 1 + a[i] - n;s = min(s, mn);}printf("%d\n", s);    }    return 0;}


1 0