题目链接:传送门
题目大意:
给定一个
n
n
n个数的序列,有
q
q
q个询问,每个询问给出区间
[
l
,
r
]
[l,r]
[l,r],要求输出
[
l
,
r
]
[l,r]
[l,r]区间内逆序对的数量。
n
,
q
<
=
5
∗
1
0
4
n,q<=5*10^4
n,q<=5∗104
容易看出,最小的交换次数=区间逆序对个数(很显然,因为一次交换只能减少一个逆序对)
然后看到这个数据范围,又是序列上的区间问题,所以想到用莫队。
发现这里莫队无法
O
(
1
)
O(1)
O(1)从
[
l
,
r
]
[l,r]
[l,r]推出
[
l
−
1
,
r
]
[l-1,r]
[l−1,r]和
[
l
,
r
+
1
]
[l,r+1]
[l,r+1]的答案。
考虑静态求数组逆序对的方法:加入时,用树状数组询问比当前权值
a
[
i
]
a[i]
a[i]大的个数。
所以这里珂以用树状数组
O
(
l
o
g
n
)
O(logn)
O(logn)维护答案qwq。
总时间复杂度:
O
(
n
n
l
o
g
n
)
.
O(n\sqrt n logn).
O(nnlogn).
代码
#include<stdio.h>
#include<cstring>
#include<algorithm>
#include<math.h>
#include<vector>
#define re register int
#define rl register ll
using namespace std;
typedef long long ll;
ll read() {
rl x=0,f=1;
char ch=getchar();
while(ch<'0' || ch>'9') {
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0' && ch<='9') {
x=10*x+ch-'0';
ch=getchar();
}
return x*f;
}
namespace I_Love {
const int Size=50005;
const int LOG=20;
int n,q,maxn,siz,a[Size],b[Size],belong[Size];
struct Day {
int id,l,r;
} Q[Size];
inline bool comp(Day x,Day y) {
if(belong[x.l]!=belong[y.l]) return belong[x.l]<belong[y.l];
return x.r<y.r;
}
//树状数组维护,记得开long long
ll ans,tree[Size],out[Size];
inline int lowbit(int x) {
return x&(-x);
}
void update(int x,int val) {
for(re i=x; i<=n; i+=lowbit(i)) {
tree[i]+=val;
}
}
ll query(int x) {
int ans=0;
for(re i=x; i; i-=lowbit(i)) {
ans+=tree[i];
}
return ans;
}
inline void addl(int x) {
ans+=query(x-1);
update(x,1);
}
inline void addr(int x) {
ans+=query(maxn)-query(x-1);
update(x,1);
}
inline void dell(int x) {
ans-=query(x-1);
update(x,-1);
}
inline void delr(int x) {
update(x,-1);
ans-=query(maxn)-query(x-1);
}
void Fujibayashi_Ryou() {
n=read();
siz=sqrt(n);
for(re i=1; i<=n; i++) {
b[i]=a[i]=read();
belong[i]=(i-1)/siz+1;
}
sort(b+1,b+1+n);
maxn=unique(b+1,b+1+n)-(b+1);
for(re i=1; i<=n; i++) {
a[i]=lower_bound(b+1,b+1+maxn,a[i])-b;
}
q=read();
for(re i=1; i<=q; i++) {
Q[i].l=read();
Q[i].r=read();
Q[i].id=i;
}
sort(Q+1,Q+1+q,comp);
int l=1,r=0;
for(re i=1; i<=q; i++) {
while(r<Q[i].r) addr(a[++r]);
while(r>Q[i].r) delr(a[r--]);
while(l<Q[i].l) dell(a[l++]);
while(l>Q[i].l) addl(a[--l]);
out[Q[i].id]=ans;
}
for(re i=1; i<=q; i++) {
printf("%lld\n",out[i]);
}
}
}
int main() {
I_Love::Fujibayashi_Ryou();
return 0;
}