题意:一个排列,每次删除一个数,求每次删除后的逆序对的数量。
正确姿势请移步 http://blog.csdn.net/u011542204/article/details/50571409
将操作分成根号M段,然后每段内的操作按下标排序,计算它前面的比他小的和它后面的比他大的。有一个问题就是同一个块当中的没有被减掉,由于一个块内只有根号M个操作,暴力减掉即可。
如果要在线的话将那个排序变成主席树即可。
时间复杂度O(M*logM*sqrt(n)),空间O(n),适当地将块调大一点会快一点。
#include
#include
#include
#include
#include
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define erp(i,a,b) for(int i=a;i>=b;--i)
#define LL long long
using namespace std;
const int MAXN = 100005;
int a[MAXN], pos[MAXN], N, M, bsz, b[MAXN], cnt, c[MAXN], r;
inline void add(int i,int x) { for(;i<=N;i+=i&-i) c[i]+=x; }
inline int qsum(int i) { for(r=0;i;i^=i&-i) r+=c[i]; return r; }
LL val[MAXN];
struct qua{
int p,id;
bool operator<(const qua&b)const{return pM) bsz = M;
rep(i,1,M) scanf("%d",b+i);
LL tot = 0;
erp(j, N, 1) tot+=qsum(a[j]-1), add(a[j],1);
for (int i=1, nex, p; i<=M; i+=bsz)
{
cnt = 0;
nex = min(M, i+bsz-1);
rep(j, i, nex) q[++cnt]=(qua){pos[b[j]],j};
sort(q+1,q+cnt+1);
p = 1;
int num = 0;
rep(j,0,N) c[j]=0;
rep(j, 1, N)
{
if (p>cnt) break;
if (a[j]<0) continue;
if (j==q[p].p) val[q[p].id]+=num-qsum(a[j]), p++;
add(a[j],1), num++;
}
p = cnt;
rep(j,0,N) c[j]=0;
erp(j, N, 1)
{
if (p<1) break;
if (a[j]<0) continue;
if (j==q[p].p) val[q[p].id]+=qsum(a[j]), p--;
add(a[j],1);
}
rep(j, i, nex)
{
rep(k, i, j-1) if (pos[b[k]]b[j]||pos[b[k]]>pos[b[j]]&&b[k]