[树状数组]LightOJ 1085 - All Possible Increasing Subsequences

1085 - All Possible Increasing Subsequences
Time Limit:3 second(s) Memory Limit:64 MB

An increasing subsequence from a sequenceA1, A2... Anis defined byAi1, Ai2... Aik, where the following properties hold

1.i1< i2< i3< ... < ikand

2.Ai1< Ai2< Ai3< ... < Aik

Now you are given a sequence, you have to find the number of all possible increasing subsequences.

Input

Input starts with an integerT (≤ 10), denoting the number of test cases.

Each case contains an integern (1 ≤ n ≤ 105)denoting the number of elements in the initial sequence. The next line will containnintegers separated by spaces, denoting the elements of the sequence. Each of these integers will be fit into a 32 bit signed integer.

Output

For each case of input, print the case number and the number of possible increasing subsequences modulo1000000007.

Sample Input

Output for Sample Input

3

3

1 1 2

5

1 2 1000 1000 1001

3

1 10 11

Case 1: 5

Case 2: 23

Case 3: 7

Notes

1.For the first case, the increasing subsequences are(1), (1, 2), (1), (1, 2), 2.

2.Dataset is huge, use faster I/O methods.

题目大意:找出一个序列中的所有上升序列,很容易想到DP,直接给代码,注释里有说明:

/**
**  构造n的状态空间, dp[i]表示以i结尾的所有上升序列的个数
**  转移为 dp[i] = 1+segma(dp[k])| 0<=k<i && arr[k]<arr[i]
**  不用树状数组优化的话转移是O(n)的
**  用树状数组优化以后转移就是O(logn)的,需要离散化
**/
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define LL long long
using namespace std;
const int MAXN = 100010;
int c[MAXN],arr[MAXN],pt[MAXN],t,n,m;
LL ans,MOD = 1000000007ll,dp[MAXN];
void init(){
    memset(c,0,sizeof(c));
    ans = 0;
}
int lowbit(int x){
    return x&(-x);
}
int sum(int pos){
    int s = 0;
    while(pos>0){
        s = (s+c[pos])%MOD;//不取模的话会溢出
        pos-=lowbit(pos);
    }
    return s;
}
void add(int pos,int val,int n){
    while(pos<=n){
        c[pos] = (c[pos]+val)%MOD;//不取模的话会溢出
        pos+=lowbit(pos);
    }
}
//离散化
void disc(){
    memcpy(pt,arr,sizeof(arr));
    sort(pt,pt+n);
    int i;
    for(i=1,m=1;i<n;i++){
        if(pt[i]!=pt[i-1])pt[m++]=pt[i];
    }
}
int search(int k){
    int l=0,r=m-1,m;
    while(l<=r){
        m = (l+r)>>1;
        if(pt[m]==k)return m;
        else if(k<pt[m])r=m-1;
        else l=m+1;
    }
    return -1;
}
int main(){
    scanf("%d",&t);
    for(int cas=1;cas<=t;cas++){
        init();
        scanf("%d",&n);
        for(int i=0;i<n;i++)scanf("%d",&arr[i]);
        disc();
        dp[0] = 1;ans = 1;
        add(search(arr[0])+1,dp[0],m);
        for(int i=1;i<n;i++){
            int pos = search(arr[i])+1;
            dp[i] = (sum(pos-1)+1)%MOD;
            ans = (ans+dp[i])%MOD;
            add(pos,dp[i],m);
        }
        printf("Case %d: %lld\n",cas,ans);
    }
    return 0;
}


你可能感兴趣的:(sequence)