bestcoder#45 1002 求区间的逆序数 树状数组

bestcoder#45 1002 求区间的逆序数  树状数组

Dylans loves sequence

 
 Accepts: 250
 
 Submissions: 806
 Time Limit: 2000/1000 MS (Java/Others)
 
 Memory Limit: 131072/131072 K (Java/Others)
问题描述
Dylans得到了NN个数a[1]...a[N]a[1]...a[N]。
有QQ个问题,每个问题形如(L,R)(L,R)
他需要求出L-RLR这些数中的逆序对个数。
更加正式地,他需要求出二元组(x,y)(x,y)的个数,使得L \leq x,y \leq RLx,yR且x < yx<y且a[x] > a[y]a[x]>a[y]
输入描述
第一行有两个数NN和QQ。
第二行给出NN个数字a[1]...a[N]a[1]...a[N]。
接下来的QQ行,每行给出两个数L, RN \leq 1000,Q \leq 100000,L \leq R,1 \leq a[i] \leq 2^{31}-1N1000,Q100000,LR,1a[i]231​​1
输出描述
对于每个询问,输出逆序对个数。
输入样例
3 2
3 2 1
1 2
1 3
输出样例
1 
3
由于数据范围比较小,只有1000,所以n^2预处理+树状数组的插入统计就行了,复杂度nlogn.

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#define REP(i,a,b) for(int i=a;i<=b;i++)
#define MS0(a) memset(a,0,sizeof(a))

using namespace std;

typedef long long ll;
const int maxn=1100;
const int INF=(1<<29);

int n,q;
ll a[maxn];
ll b[maxn],m;
int L,R;
ll c[maxn];
ll ans[maxn][maxn];

int lowbit(int x)
{
    return x&(-x);
}

ll sum(int p)
{
    ll res=0;
    while(p>0){
        res+=c[p];
        p-=lowbit(p);
    }
    return res;
}

void add(int p,int x)
{
    while(p<=m){
        c[p]+=x;
        p+=lowbit(p);
    }
}

int main()
{
    while(~scanf("%d%d",&n,&q)){
        REP(i,1,n) scanf("%I64d",&a[i]),b[i]=a[i];
        sort(b+1,b+n+1);
        m=unique(b+1,b+n+1)-(b+1);
        MS0(ans);
        REP(i,1,n){
            MS0(c);
            REP(j,i,n){
                int x=lower_bound(b+1,b+m+1,a[j])-b;
                add(x,1);
                ans[i][j]+=ans[i][j-1]+sum(m)-sum(x);
            }
        }
        while(q--){
            scanf("%d%d",&L,&R);
            printf("%I64d\n",ans[L][R]);
        }
    }
    return 0;
}
View Code

 



posted @ 2015-10-06 17:28  __560  阅读(312)  评论(0编辑  收藏  举报