题目大意:给定一个数组a[n],输入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; }