• hdu 2227


    Find the nondecreasing subsequences

    Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 1564    Accepted Submission(s): 563


    Problem Description
    How many nondecreasing subsequences can you find in the sequence S = {s1, s2, s3, ...., sn} ? For example, we assume that S = {1, 2, 3}, and you can find seven nondecreasing subsequences, {1}, {2}, {3}, {1, 2}, {1, 3}, {2, 3}, {1, 2, 3}.
     
    Input
    The input consists of multiple test cases. Each case begins with a line containing a positive integer n that is the length of the sequence S, the next line contains n integers {s1, s2, s3, ...., sn}, 1 <= n <= 100000, 0 <= si <= 2^31.
     
    Output
    For each test case, output one line containing the number of nondecreasing subsequences you can find from the sequence S, the answer should % 1000000007.
     
    Sample Input
    3 1 2 3
     
    Sample Output
    7
     
    Author
    8600
     
    Recommend
    lcy
     
    题目描述 :求一段序列的上海上升序列的个数 dp[i]= sum(dp[j]+1) &&(a[j]<a[i])
    因为a[j]<a[i] ,所以相当于求正序数的个数 
    求逆序数一般有三种解法 1 暴力 2 归并排序 3 树状数组 
    树状数组求法 :
    原始序列为 5 4  1 2 3
    int answer=0;
    一 在1的位置上加一       answer+=sum(i-1); answer=0; 
    0 0 1 0 0
    二在2的位置上加一       answer+=sum(3); answer=1;
    0 0 1 1 0
    三在3的位置上加一       answer+=sum(4); answer=3 
    0 0 1  1 1
    四 在四的位置上加一  answer+=sum(1);answer=3;
    0  1 1 1  1
    五 在五的位置上加一  answer+=sum(0);answr=3;
    1 1 1 1 1
    此题要求所有的上升序列的个数,有了递推式应该很好求,
    可是我陷入了一个误区 ,认为既然是递推式,那么就应该按照天然的顺序,逐个递推(因为计算当前状态值需要用到前面所有的状态值),
    可是要求正序数的话需要从小到大,逐个放入,计算前面的数之和,瞬间就无语了,怎么办呢?观察递推式  dp[i]= sum(dp[j]+1) &&(a[j]<a[i])
    如果从小到大放的话,假设放i位置,那么i之前的就是比它小的已经放过的,没有放的就是对i状态的值无影响的,先放还是后放对i
    状态没有影响,这样我们就可以去掉对i来说的冗余信息,相当于只对 a[j] < a[i] 的 j 进行递推,
    我们设 A[i]代表以i结尾的上升序列的个数,A[i]=sum(i-1)+1;sum(i-1)代表之前所有的上升序列的个数,sum(i-1) == A[1]+A[2]+A[3]+.....+A[i-1];
    假设从小到大进行求解,利用暴力求和,时间复杂度太高,
    那么我们利用树状数组进行点(A[i])修改和查询操作,时间复杂度降为 long(N);
    也可利用线段树进行点修改和查询操作
    采用树状数组,从小到大 ,放入 它自己的位置,然后更新A[i],那么答案就是sum(N);
    假设原始序列为 5 4  1 2 3
    0 0 0 0 0
    0 0 1 0 0
    0 0 1 2 0
    0 0 1 2 4
    0 1 1 2 4
    1 1 1 2  4
    那么答案就是1 + 1 + 1 + 2 + 4=9,利用树状数组进行求和 
    #include <iostream>
    #include <cstdio>
    #include <time.h>
    #include <stdlib.h>
    #include <cstring>
    #include<algorithm>
    #define M 100100
    #define MOD 1000000007
    #define LL  long long
    using namespace std;
    struct node
    {
       LL value,id;
    };
    bool cmp (node a,node b)
       {
           if(a.value!=b.value)
           return a.value<b.value;
           else
           return a.id<b.id;
       }
    node a[M];
    LL dp[M];
    LL c[M];
    LL N;
    void init()
    {
       memset(a,0,sizeof(a));
       memset(dp,0,sizeof(dp));
       memset(c,0,sizeof(c));
    }
    
    //树状数组
    LL lowbit(LL x)
    {
       return x&(-x);
    }
    
    LL sum(LL x)
    {
       LL ret=0;
       while(x>0)
       {
          ret=ret%MOD;
          ret+=c[x];
          x-=lowbit(x);
       }
        return ret%MOD;
    }
    
    void  add(LL x,LL extra)
    {
        while(x <= N)
        {
          c[x]=c[x]%MOD;
          c[x]=c[x]+1+extra;     //A[i]加上i之前的所有的上升序列的个数 A[i]=sum(i-1)+1;sum(i-1)代表之前所有的上升序列的个数
          x+=lowbit(x);
        }
    }
    
    LL solve()
    {
        add(a[1].id,0);
       //  answer+=sum(a[1].id);
        //printf("%lld
    ",sum(a[1].id));
        for(int i=2;i<=N;i++)
        {
                add(a[i].id,sum(a[i].id-1));  //A[i]加上i之前的所有的上升序列的个数 A[i]=sum(i-1)+1;sum(i-1)代表之前所有的上升序列的个数
               // answer=answer % MOD;
               // answer+=sum(a[i].id);
            // printf("%lld
    ",sum(a[i].id));
        }
        return sum(N) % MOD;
    }
    
    int main()
    {
        while(~scanf("%d",&N))
        {
          init();
          for(int i=1;i<=N;i++)
          {
            scanf("%I64d",&a[i].value);
            a[i].id=i;
             //printf("%I64d  %I64d
    ",a[i].value,a[i].id);
          }
          /*for(int i=1;i<=N;i++)
          {
           printf("%lld  %lld
    ",a[i].value,a[i].id);
    
          }*/
              sort(a+1,a+N+1,cmp);
    
              printf("%I64d
    ",solve());
        }
    
        return 0;
    }
  • 相关阅读:
    互联网成为基础设施,数据成为生产资料,计算成为公共服务。让计算成为人类的能力,让数据成为世界的财富
    数据本没有价值,就像你留在地上的脚印,直到你有计算能力去处理才会产生价值。计算,如同其他基础设施一样,能够把沉寂的数据“沙子”变成经济、产业、财富的“金矿”。
    100多年前,铁路在美国成为基础设施,为美国带来翻天覆地的变化。今天互联网作为基础设施,对中国未来发展的推动绝对不会亚于当年铁路给美国带来的变化。
    HDU--1060
    素数
    欧几里德算法与扩展欧几里德算法
    HDU--1164
    挨踢人生路
    HDU题目分类
    HDU--2087
  • 原文地址:https://www.cnblogs.com/xianbin7/p/4471772.html
Copyright © 2020-2023  润新知