题目链接:bzoj-3289-Mato的文件管理
最大交换次数应该是区间的逆序对数,每次交换消除一个逆序对(不会证明)。
求逆序对可以用树状数组来实现。每次转移是
O(logn)
的。
因此总复杂度是
O(n32logn)的
。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=55000;
int c[maxn],d[maxn],pos[maxn];
int a[maxn];
int n,L,R,m;
ll Ans,ans[maxn];
struct Query
{
int l,r,id;
bool operator < (const Query & b) const
{
return pos[l]<pos[b.l]||(pos[l]==pos[b.l]&&r<b.r);
}
}Q[maxn];
inline int lowbit(int x)
{
return x&-x;
}
inline void modify(int x,int k)
{
for(;x<maxn;x+=lowbit(x))
c[x]+=k;
}
inline int sum(int x)
{
int res=0;
for(;x>0;x-=lowbit(x))
res+=c[x];
return res;
}
int main()
{
while(~scanf("%d",&n))
{
int sz=sqrt(n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
d[i]=a[i];
pos[i]=i/sz;
}
sort(d+1,d+n+1);
for(int i=1;i<=n;i++)
a[i]=lower_bound(d+1,d+n+1,a[i])-d;
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
cin>>Q[i].l>>Q[i].r;
Q[i].id=i;
}
sort(Q+1,Q+1+m);
L=1;R=0;Ans=0;
memset(c,0,sizeof(c));
for(int i=1;i<=m;i++)
{
while(R<Q[i].r)
{
++R;
modify(a[R],1);
Ans+=R-L+1-sum(a[R]);
}
while(R>Q[i].r)
{
modify(a[R],-1);
Ans-=R-L-sum(a[R]);
--R;
}
while(L<Q[i].l)
{
modify(a[L],-1);
Ans-=sum(a[L]);
++L;
}
while(L>Q[i].l)
{
--L;
modify(a[L],1);
Ans+=sum(a[L]-1);
}
if(Q[i].id>=maxn) while(1);
ans[Q[i].id]=Ans;
}
for(int i=1;i<=m;i++)
printf("%lld\n",ans[i]);
}
return 0;
}