您的位置:首页 > 其它

BZOJ 3289 莫队 树状数组

2016-01-25 18:10 323 查看
BZOJ 3289

题目链接:

http://www.lydsy.com/JudgeOnline/problem.php?id=3289

题意:

问[L,R]区间最少交换几次相邻数字使得整个序列有序。

思路:

统计逆序对,用树状数组。然后跑一遍莫队。

离散化部分容易超时,所以直接修改了数组。

源码:

[code]#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <string>
#include <algorithm>
#include <iostream>
#include <vector>
#include <map>
using namespace std;
#define LL unsigned int
const int MAXN = 50000 + 5;
int tr[MAXN * 2];       ///tree array
int cnt;
int lowbit(int u){return u & -u;}
void update(int u, int v)
{
    for(; u <= cnt ; u += lowbit(u)){
        tr[u] += v;
    }
}
LL query(int u)
{
    LL ans = 0;
    for(; u; u -= lowbit(u)) {
        ans += tr[u];
    }
    return ans;
}
int data[MAXN];
int pos[MAXN];
int blocksize;
int n, m;
struct Q
{
    int l, r, id;
}q[MAXN];
bool cmp(Q a, Q b)
{
    if(pos[a.l] == pos[b.l]) return a.r < b.r;
    return a.l < b.l;
}
int tt[MAXN];
LL res[MAXN];
map<int,int>mm;
int main()
{
//    freopen("BZOJ 3289.in", "r", stdin);
    while(scanf("%d", &n) != EOF){
        blocksize = sqrt(1.0 * n);
        for(int i = 1 ; i <= n ; i++) scanf("%d", &data[i]), tt[i] = data[i], pos[i] = (i - 1) / blocksize;
        sort(tt + 1 , tt + 1 + n);
        mm.clear();
        cnt = 0;
        for(int i = 1 ; i <= n ; i++){  ///离散化
            if(mm[tt[i]] == 0) mm[tt[i]] = ++cnt;
        }
        for(int i = 1 ; i <= n ; i++) data[i] = mm[data[i]];
//        for(int i = 1 ; i <= n ; i++) printf("data[i] = %d, mm = %d\n", data[i], mm[data[i]]);
//        printf("cnt = %d\n", cnt);
//        system("pause");
        scanf("%d", &m);
        for(int i = 0 ; i < m ; i++) scanf("%d%d", &q[i].l, &q[i].r), q[i].id = i;
        sort(q, q + m, cmp);
        int curr = 0;
        int curl = 1;
        memset(tr, 0, sizeof(tr));
        LL ans = 0;
        for(int i = 0 ; i < m ; i++){
            for(int j = curr + 1 ; j <= q[i].r ; j++) update(data[j], 1), ans += j - curl + 1 - query(data[j]);
//            printf("ans = %I64d\n", ans);
            for(int j = curr ; j > q[i].r ; j--) update(data[j], -1), ans -= j - curl - query(data[j]);
//            printf("ans = %I64d\n", ans);
            curr = q[i].r;
            for(int j = curl ; j < q[i].l ; j++) update(data[j], -1), ans -= query(data[j] - 1);
//            printf("ans = %I64d\n", ans);
            for(int j = curl - 1 ; j >= q[i].l ; j--) update(data[j], 1), ans += query(data[j] - 1);
//            printf("ans = %I64d\n", ans);
            curl = q[i].l;
            res[q[i].id] = ans;
//            printf("l = %d, r = %d, ans = %I64d\n", q[i].l, q[i].r, ans);
        }
        for(int i = 0 ; i < m ; i++) printf("%d\n", res[i]);
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: