您的位置:首页 > 其它

hdu5273 n次查询求逆序数对

2015-06-20 22:27 260 查看
题目大意:给定一个数组a,输入q次查询(如b,c),输出从a[b] 到a[c] 从在多少逆序数对
N只有1000,刚开始居然n^3,一直没想到,就在那里推一维数组,二维的闪现了一下但是忽略了。
仔细一想发现可以很简单地做到N2.
设dp[l][r]表示从l~r的逆序对数量。首先我们暴力地先算好dp[1][1..N]。
然后i从2∼N枚举,每次计算从i开始的逆序对。
那么dp[i][j]比dp[i-1][j]少了什么呢?没错,少了a[i−1]这个数的贡献。
我们再开一个累加器cnt。枚举j从i∼N,如果a[i-1]和a[j]构成逆序数,则cnt--;
最后dp[i][j]=dp[i−1][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;
}
[/code]

                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: