HDU 5273 Dylans loves sequence (逆序对,暴力)

题意:给定一个序列,对于q个询问:(L,R)之间有几个逆序对?序列元素个数上限1000,q上限10万。仅1测试例子。

思路:

先分析:

  [L,R]的逆序对数量可以这么算,假设L<=K<R,将区间拆成两部分,那么[L,k]中的逆序对要算上, (k,R]中的逆序对也要算上,还有一些逆序对假设为(l,r),l在左部分,r在右部分。则应该是3部分来构成,设3部分为A,B,C,那么ans=A+B+C 。

  而如果将k移到最右边,比如k=R-1,那么区间拆成[L,k]和(K,R],而(K,R]其实就只有R一个元素,并不存在什么逆序对,所以B=0,那么ans=A+C,仅仅由两部分构成,就简单了。

  对于序列a,假设m[j][i]表示从j到i-1之间有几个大于a[i](如果知道了j到i-1之间有多少逆序对,那么再加上m[j][i]就是j到i之间的逆序对数了)。复杂度1k*1k。

  接着求答案了,假设ans[L][R]表示从L到R之间有多少个逆序对,那么ans[j][i]=ans[j][i-1]+m[j][i]。而我们知道ans[j][j]肯定为0,那么就能计算出其他的答案了。复杂度1k*1k。

(也可以对于每个询问才来求ans[L][R],复杂度10w*1k还是可以过的)

 1 #include <iostream>
 2 #include <cmath>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <map>
 6 #include <vector>
 7 #include <set>
 8 #include <map>
 9 #define LL long long
10 using namespace std;
11 const int N=1005;
12
13 int a[N];
14 int m[N][N];
15 int ans[N][N];
16 int n, q;
17
18 void cal()
19 {
20     memset(m,0,sizeof(m));
21     memset(ans,0,sizeof(ans));
22
23     for(int i=1; i<=n; i++)
24     {
25         for(int j=i-1; j>0; j--)
26             if(a[j]>a[i])    m[j][i]=m[j+1][i]+1;   //计算在j~i-1之间比a[i]大的有几个
27             else    m[j][i]=m[j+1][i];
28     }
29
30     for(int i=1 ;i<=n; i++)
31         for(int j=i+1; j<=n; j++)
32             ans[i][j]=ans[i][j-1]+m[i][j];
33
34 }
35
36
37 int main()
38 {
39     //freopen("input.txt", "r", stdin);
40     int aa,bb;
41     while(~scanf("%d%d",&n,&q))
42     {
43         for(int j=1; j<=n; j++)
44             scanf("%d",&a[j]);
45
46         cal();
47         while(q--)
48         {
49             scanf("%d%d",&aa,&bb);
50             printf("%d\n",ans[aa][bb]);
51         }
52     }
53
54     return 0;
55 }

AC代码

时间: 2024-11-17 10:58:02

HDU 5273 Dylans loves sequence (逆序对,暴力)的相关文章

hdu 5273 Dylans loves sequence 逆序数简单递推

Dylans loves sequence Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5273 Description Dylans得到了N个数a[1]...a[N].有Q个问题,每个问题形如(L,R)他需要求出L−R这些数中的逆序对个数.更加正式地,他需要求出二元组(x,y)的个数,使得L≤x,y≤R且x<y且a[x]>a[y] Input 第一行有两个数N和Q

HDU 5273 Dylans loves sequence(区间DP)

Dylans loves sequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 114    Accepted Submission(s): 59 Problem Description Dylans is given N numbers a[1]....a[N] And there are Q questions. E

hdu 5273 Dylans loves sequence(区间逆序对数-莫队算法)

n<=1000,q<=100000,求区间内逆序对数,从[l,r]显然可以log(n)的时间内移动到[l-1,r],[l+1,r],[l,r-1],[l,r+1],那么就可以用莫队进行离线 复杂度大概是O(n*sqrt(n)*log2(n)),不过可以暴力枚举起点,然后向后统计,然后O(1)回答,不过n再大就无法解决了,这个即使是n<=1e5也可以很快得到答案,开-o优化,1e6也可以很快得到答案 #include<bits/stdc++.h> using namespace

HDU 5273 Dylans loves sequence【 树状数组 】

题意:给出n个数,再给出q个询问,求L到R的逆序对的个数 先自己写的时候,是每次询问都重新插入来求sum(r)-sum(l) 果断T 后来还是看了别人的代码---- 预处理一下,把所有可能的区间的询问都求出来(1000*1000), 然后询问就是O(1)了 然后想自己这样写超时,是因为询问太多了---- 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include <cmath>

hdu 5273 Dylans loves sequence

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5273 bestcoder round#45 1002 题目大意: 给出一个有n个数的任意序列,问[r,l]区间内一共有多少对倒置数? 解题思路: 由于1<=n<=1000,所以想怎么做怎么做,当时不知道怎么了,思路不错,但是就是代码wa. 1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h&

HDU 5273 Dylans loves numbers(水题)

题意:给出一个0≤N≤1018,求其二进制中有几处是具有1的,假设相连的1只算1处,比如1101011就是3处. 思路:一个个数,当遇到第一个1时就将flag置为1:当遇到0就将flag置为0.当遇到1时,flag=0就统计,当flag=1时就不统计. 1 #include <bits/stdc++.h> 2 #define LL long long 3 using namespace std; 4 5 int main() 6 { 7 int t; 8 LL n; 9 cin>>

【BC#24 1002 HDOJ 5273】Dylans loves sequence

[BC#24 1002 HDOJ 5273]Dylans loves sequence 逆序对动归 比赛时候各种奇葩姿势都上了个遍 归并也憋出来了 谁知道就给我看这个.... 赛后有的思路 收到赛后题解的启发 dp[l][r]是l~r之间逆序对 先暴力把dp[1][1~n]枚举出来 然后i从2~n枚举左边界 右边界从i+1~n 这样dp[i][j] 即求出了区间左端点从2往后的所有逆序对数 而dp[i][j]即为dp[i-1][j]中吧i-1的逆序对数减去的余数 这样顺序暴力即可......还是

HDU 4911 Inversion(归并求逆序对)

HDU 4911 Inversion 题目链接 题意:给定一个数组,可以相邻交换最多k次,问交换后,逆序对为多少 思路:先利用归并排序求出逆序对,然后再减去k就是答案 代码: #include <stdio.h> #include <string.h> #include <algorithm> using namespace std; const int N = 100005; int n, num[N], save[N], sn; void init() { for

HDU ACM 5273 Dylans loves sequence-&gt;DP

题意:给定一组数,q次查询(每次区间l~r),输出从a[l] 到a[r] 存在多少对逆序数. 分析:dp[l][r]表示从l~r的逆序数对数.首先算好dp[1][1..N]. 然后2-N枚举,每次计算从i开始的逆序对.dp[i][j]比dp[i-1][j]少了a[i-1]这个数的贡献.设一个累加器cnt.枚举i-N,若a[i-1]和a[j]构成逆序数,则cnt++: 最后dp[i][j]=dp[i-1][j]-cnt. 这题也可用树状数组,但感觉麻烦. #include<iostream> u