hdu5273 n次查询求逆序数对

题目大意:给定一个数组a[n],输入q次查询(如b,c),输出从a[b] 到a[c] 从在多少逆序数对

N只有
   
    1000
   ,刚开始居然n^3,一直没想到,就在那里推一维数组,二维的闪现了一下但是忽略了。
仔细一想发现可以很简单地做到
   
    N2
   .
设dp[l][r]表示从l~r的逆序对数量。首先我们暴力地先算好
   
    dp[1][1..N]
   。
然后
   
    i
   
   
    2N
   枚举,每次计算从
   
    i
   开始的逆序对。
那么dp[i][j]
   
    dp[i-1][j]
   少了什么呢?没错,少了
   
    a[i1]
   这个数的贡献。
我们再开一个累加器
   
    cnt
   。枚举
   
    j
   
   
    iN
   ,如果a[i-1]和a[j]构成逆序数,则cnt--;
最后
   
    dp[i][j]=dp[i1][j]+cnt[j]
   。
预处理完所有的答案就可以
   
    O(1)
   的询问啦
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>

using namespace std;

int dp[1005][1005];
int a[1005];
int cnt[1005];

int main()
{
    int N , Q;
    while(scanf("%d%d" , &N , &Q)!= EOF)
    {
        for(int i = 1 ; i <= N ; i ++ ) scanf("%d", &a[i]);
        memset(dp,0,sizeof(0));
        for(int i = 1 ; i <= N ; i ++ )
        {
            for(int j = 1 ; j < i ; j ++ )
            {
                if(a[i] < a[j]) dp[1][i] ++ ;
            }
            dp[1][i] += dp[1][i-1];
        }
        for(int i = 2 ; i <= N ; i ++ )
        {
            int ans = 0;
            for(int j = i ; j <= N ; j ++ )
            {
                if(a[i - 1] > a[j]) ans -= 1 ;
                dp[i][j] = dp[i-1][j] + ans;
            }

        }
        for(int i = 0 ; i < Q ; i ++ )
        {
            int b , c;
            scanf("%d%d", &b , &c);
            printf("%d\n" , dp[b][c]);
        }
    }
    return 0;
}


 
 

你可能感兴趣的:(hdu5273 n次查询求逆序数对)