BZOJ 3289
题目链接:
http://www.lydsy.com/JudgeOnline/problem.php?id=3289
题意:
问[L,R]区间最少交换几次相邻数字使得整个序列有序。
思路:
统计逆序对,用树状数组。然后跑一遍莫队。
离散化部分容易超时,所以直接修改了数组。
源码:
#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;
}