【线段树】——坐标离散化——lightoj1085

                                                                                   

                                                         LightOJ 1085

                                        Time Limit:3000MS     Memory Limit:65536KB     64bit IO Format:%lld & %llu
                                                                                   

Description

An increasing subsequence from a sequence A1, A2 ... An is defined by Ai1, Ai2 ... Aik, where the following properties hold

  1. i1 < i2 < i3 < ... < ik and
  2. 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 integer T (≤ 10), denoting the number of test cases.

Each case contains an integer n (1 ≤ n ≤ 105) denoting the number of elements in the initial sequence. The next line will contain n integers 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 modulo 1000000007.

Sample Input

3

3

1 1 2

5

1 2 1000 1000 1001

3

1 10 11

Sample Output

Case 1: 5

Case 2: 23

Case 3: 7

 

题意:求所有上升子序列的个数

技巧:<algorithm>里的:unique,lower_bound(),up_bound;

        

附上代码:

 

//离散化数据+树状数组统计每个之前出现在该数之前的子序列数
#include<bits/stdc++.h>
using namespace std;

#define mod 1000000007
#define maxn (100000 + 50)
#define lowbit(x) (x & (-x))

int a[maxn];//原数组(用于看放入元素的顺序)
int ac[maxn];//排序数组(用于比较元素大小——即离散化)
int c[maxn];//建树数组

void add(int x,int ad,int n)
{
    while(x<=n)
    {
        c[x] = (c[x] + ad) % mod;
        x = x + lowbit(x);
    }
}

int sum(int n)
{
    int s=0;
    while(n>0)
    {
        s=(s+c[n])%mod;
        n=n-lowbit(n);
    }
    return s%mod;
}

int main()
{
    int t,n;
    scanf("%d",&t);

    for(int z=1;z<=t;z++)
    {
        scanf("%d",&n);

        memset(c,0,sizeof(c));

        for(int i = 1; i <= n; i ++)
        {
            scanf("%d",&a[i]);
            ac[i] = a[i];
        }

        sort(ac+1 , ac+n+1);
        //unique是将相同元素放至数组后,返回的是新数组(此题中:单增数组)的地址np+1
        //np表示新数组的大小(偏移量)
        int np = unique (ac+1 , ac+n+1) - ac;

        for(int i=1;i<=n;i++)
        {
            //lower_bound返回第一个小于等于a[i]的元素地址
            //pos表示第一个小于等于a[i]的元素的位置
            int pos = lower_bound(ac+1 , ac + np, a[i]) - ac;
            add(pos , sum(pos - 1)+1 , np - 1);
        }
        printf("Case %d: %d\n",z,sum(np-1));
    }
    return 0;
}

 

posted @ 2016-04-27 17:51  琥珀川||雨露晨曦  阅读(91)  评论(0)    收藏  举报