「NOIP模拟」蒜头君的排序【伪莫队】【树状数组】

求冒泡排序的交换次数即求逆序对数。

按照正常的求逆序对的方法和莫队方法添加删除即可。

注意不要把每次的ans清零。

#include <cmath>
#include <bitset>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define db double
#define sg string
#define rel(i,x,y) for(int i=(x);i<(y);i++)
#define rep(i,x,y) for(int i=(x);i<=(y);i++)
#define red(i,x,y) for(int i=(x);i>=(y);i--)
#define res(i,x) for(int i=head[x];i;i=nxt[i])
using namespace std;

const int N=1e5+5;
const int Inf=1e18;
const db Eps=1e-10;

int n,m,ans,a[N],bit[N];

#define lowbit(x) (x&(-x))

inline int read() {
	int x=0;char ch=getchar();bool f=0;
	while(ch>'9'||ch<'0'){if(ch=='-')f=1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
	return f?-x:x;
}

void update(int x,int k) {
	while(x<=n) bit[x]+=k,x+=lowbit(x);
}

int getsum(int x) {
	int ret=0;while(x) ret+=bit[x],x-=lowbit(x);return ret;
}

int main() {
	n=read();
	
	rep(i,1,n) a[i]=read();
	
	m=read();
	
	int l=1,r=0;
	
	while(m--) {
		int x=read(),y=read();
		
		while(r>y) {
			update(a[r],-1);ans-=getsum(n)-getsum(a[r]-1);r--;
		}
		
		while(r<y) {
			r++;ans+=getsum(n)-getsum(a[r]-1);update(a[r],1);
		}
		
		while(l<x) {
			update(a[l],-1);ans-=getsum(a[l]-1);l++;
		}
		
		while(l>x) {
			l--;ans+=getsum(a[l]-1);update(a[l],1);
		}
		
		printf("%d\n",ans);
	}

	return 0;
}

猜你喜欢

转载自blog.csdn.net/yanzhenhuai/article/details/83474783