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。
第二行给出N个数字a[1]...a[N]。
接下来的Q行,每行给出两个数L,R。

N≤1000,Q≤100000,L≤R,1≤a[i]≤231−1

Output

对于每个询问,输出逆序对个数。

Sample Input

3 2
3 2 1
1 2
1 3

Sample Output

1
3

HINT

题意

题解:

N只有1000,于是想怎么来就怎么来。
最容易想到的是枚举开头,然后Nlog(N)时间里去算逆序对,用一个树状数组维护。
(可惜BC不给卡。。。呜呜呜)
仔细一想发现可以很简单地做到N2.
设ans[l][r]为l∼r的逆序对数量。首先我们暴力地先算好ans[1][1..N]。
然后i从2∼N枚举,每次计算从i开始的逆序对。
那么ans[i][j]比ans[i−1][j]少了什么呢?没错,少了a[i−1]这个数的贡献。
我们再开一个累加器cnt。枚举j从i∼N,如果a[i−1]和a[j]产生逆序对就cnt[j]=−1
然后我们从右往左累加cnt(因为贡献是前缀和性质的)
最后ans[i][j]=ans[i−1][j]+cnt[j]。
预处理完所有的答案就可以O(1)的询问啦。

代码

#include <cstdio>
#include <cmath>
#include <cstring>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
#include <sstream>
#include <queue>
#include <typeinfo>
#include <fstream>
#include <map>
#include <stack>
typedef long long ll;
using namespace std;
//freopen("D.in","r",stdin);
//freopen("D.out","w",stdout);
#define sspeed ios_base::sync_with_stdio(0);cin.tie(0)
#define test freopen("test.txt","r",stdin)
#define maxn 2000001
#define mod 10007
#define eps 1e-9
const int inf=0x3f3f3f3f;
const ll infll = 0x3f3f3f3f3f3f3f3fLL;
inline ll read()
{
    ll x=0,f=1;char ch=getchar();
    while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
//**************************************************************************************

int d[1005][1005];
int sum[1005][1005];
int a[1005];
int main()
{
    int n=read(),q=read();
    for(int i=1;i<=n;i++)
        a[i]=read();
    for(int i=1;i<=n;i++)
    {
        for(int j=i+1;j<=n;j++)
        {
            if(a[j]<a[i])
                d[i][j]=d[i][j-1]+1;
            else d[i][j]=d[i][j-1];
        }
        for(int j=i-1;j>=1;j--)
        {
            if(a[j]>a[i])
                d[i][j]=d[i][j+1]+1;
            else
                d[i][j]=d[i][j+1];
        }
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=i;j<=n;j++)
            sum[i][j]=sum[i][j-1]+d[j][i];
    }
    while(q--)
    {
        int x=read(),y=read();
        printf("%d\n",sum[x][y]);
    }
}

时间: 2024-12-24 11:34:52

hdu 5273 Dylans loves sequence 逆序数简单递推的相关文章

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一

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

题目链接: 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 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 step 3.1.1)超级楼梯(简单递推:从第1级到第m级有多少种走法,每次只能走一步或两步)

在写题解之前给自己打一下广告哈~..抱歉了,希望大家多多支持我在CSDN的视频课程,地址如下: http://edu.csdn.net/course/detail/209 题目: 超级楼梯 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 652 Accepted Submission(s): 483   Problem Description

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(求逆序数)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4911 Inversion Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 528    Accepted Submission(s): 228 Problem Description bobo has a sequence a1,a2,