转载请注明出处,http://blog.youkuaiyun.com/Bule_Zst/article/details/77119396
题目:http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1473
Description
给出一个包含N个各不相同的整数的序列,求其递增子序列的个数。
输入的第一行为测试数据的组数T (T > 0)。
Input
每组测试数的第一行为一个整数N (1 ≤ N ≤
105
),表示序列中一共有N个整数。接下来一行包含N个小于109的各不相同的非负整数,依次描述了这个序列中的各个整数。
Output
对于每组测试数据,输出递增子序列的个数。由于结果可能会很大,所以只需要输出结果除以1000000007所得的余数即可。
Sample Input
2
3
1 2 3
4
3 1 4 2
Sample Output
7
7
方法:树状数组 详见 搞懂树状数组
用map记录数据的位置,根据数据的大小从小到大进行排序,然后依次传入函数,更新c数组。
c数组是用来求和a数组(a数组在代码中没有定义,存在在想象中)的,a[i]表示 对于原整数串,以第i位结尾的递增子序列的个数。
因为数据排过序,所以对于每次传入的 位置信息对应的数p 一定大于之前传入的,因此,对于传入的位置信息n,只需要求和a[1], a[2]…a[n-1](PS: 此时,比p大的数还未加入到a数组中),然后加到a[n]上,多加的1代表自身(一个数也认为是一个递增序列)。
// @Team : nupt2017team12
// @Author : Zst
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <vector>
#include <cmath>
#include <algorithm>
#include <map>
using namespace std;
#define LL long long
#define MOD 1000000007
#define CLR(a,x) memset(a,x,sizeof(a))
#define INF 0x3f3f3f3f
#define pb push_back
#define FOR(i,a,b) for( int i = ( a ); i <= ( b ); i++ )
const int N = 1e5+7;
int n;
int A[N];
int sorted[N];
map<int,int> Map;
int tree[N];
void add( int sub, int x )
{
while( sub <= n ) {
tree[sub] = ( tree[sub] + x ) % MOD;
sub += ( sub & ( -sub ) );
}
}
int sum( int x )
{
int ans = 0;
while( x > 0 ) {
ans = ( ans + tree[x] ) % MOD;
x -= ( x & ( -x ) );
}
return ans;
}
int main()
{
// freopen( "H.txt", "r", stdin );
int w;
scanf( "%d", &w );
while( w-- ) {
CLR( tree, 0 );
Map.clear();
scanf( "%d", &n );
FOR( i, 1, n ) {
scanf( "%d", A + i );
sorted[i] = A[i];
}
sort( sorted+1, sorted+n+1 );
FOR( i, 1, n ) {
Map[sorted[i]] = i;
}
FOR( i, 1, n ) {
int rank = Map[A[i]];
add( rank, sum( rank - 1 )+1 );
}
printf( "%d\n", sum( n ) );
}
return 0;
}