【线段树】——坐标离散化——lightoj1085
Description
An increasing subsequence from a sequence A1, A2 ... An is defined by Ai1, Ai2 ... Aik, where the following properties hold
- i1 < i2 < i3 < ... < ik and
- 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; }

浙公网安备 33010602011771号