标签:
1、题意:排序交换的次数就是逆序对的个数,所以就是求区间逆序对
2、分析:本蒟蒻太垃圾,不会在线做法,直接离线了,思考一下逆序对的求法,跑一边树状数组就好,那么我们使用莫队算法,每次转移的时候就按照这个点对答案的贡献,然后把贡献减掉就行了,时间复杂度
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
#define M 100010
inline int read(){
char ch = getchar(); int x = 0, f = 1;
while(ch < ‘0‘ || ch > ‘9‘){
if(ch == ‘-‘) f = -1;
ch = getchar();
}
while(‘0‘ <= ch && ch <= ‘9‘){
x = x * 10 + ch - ‘0‘;
ch = getchar();
}
return x * f;
}
int a[M], b[M], block[M], block_size;
struct Node{
int l, r, id;
inline bool operator < (const Node& rhs) const{
return block[l] < block[rhs.l] || block[l] == block[rhs.l] && block[r] < block[rhs.r] || block[l] == block[rhs.l] && block[r] == block[rhs.r] && l < rhs.l;
}
} que[M];
int C[M], tot, res[M];
inline void add(int x, int y){
for(; x <= tot; x += x & -x) C[x] += y;
}
inline int query(int x){
int ret = 0;
for(; x > 0; x -= (x & -x)) ret += C[x];
return ret;
}
int main(){
//freopen("0input.in", "r", stdin);
int n = read();
for(int i = 1; i <= n; i ++) a[i] = b[i] = read();
sort(b + 1, b + n + 1);
int L = unique(b + 1, b + n + 1) - b - 1; tot = L;
for(int i = 1; i <= n; i ++) a[i] = lower_bound(b + 1, b + L + 1, a[i]) - b;
block_size = sqrt(n);
for(int i = 1; i <= n; i ++) block[i] = i / block_size + 1;
int q = read();
for(int i = 1; i <= q; i ++) que[i].l = read(), que[i].r = read(), que[i].id = i;
sort(que + 1, que + q + 1);
int l = que[1].l, r = que[1].l - 1, ans = 0;
for(int i = 1; i <= q; i ++){
while(l < que[i].l){
add(a[l], -1); ans -= query(a[l] - 1); l ++;
}
while(l > que[i].l){
l --; add(a[l], 1); ans += query(a[l] - 1);
}
while(r < que[i].r){
r ++; add(a[r], 1); ans += r - l + 1 - query(a[r]);
}
while(r > que[i].r){
add(a[r], -1); ans -= r - l - query(a[r]); r --;
}
res[que[i].id] = ans;
}
for(int i = 1; i <= q; i ++) printf("%d\n", res[i]);
return 0;
}
标签:
原文地址:http://blog.csdn.net/qzh_1430586275/article/details/52276233