Find the nondecreasing subsequences(数状数组+离散化+dp)

来源:互联网 发布:ubuntu无法登录界面 编辑:程序博客网 时间:2024/06/04 19:27

Problem B

Time Limit : 10000/5000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other)
Total Submission(s) : 70   Accepted Submission(s) : 17
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
31 2 3
 

Sample Output
7

题意:

给你一串数字,问共有多少个不递减的子序列。

思路:

一看到不递减立马想到了逆序数,一想到逆序数又想到数状数组,题目的难点在于dp思想的运用。这一点是非常不好理解的。就是还要注意求和会溢出,要求余mod。

代码:

#include <iostream>#include <stdio.h>#include <cstdio>#include <cstring>#include <algorithm>#define mod 1000000007typedef long long ll;using namespace std;int n;int c[100010],b[100010],t[100010];struct node{int v;int id;bool operator<(const node&b)const{return v<b.v; } }a[100010]; int lowbit(int x){return x&(-x);}int sum(int x){int res=0;while(x>0){res+=c[x];if(res>=mod)res%=mod;x-=lowbit(x);}return res;}void add(int i,int v){while(i<=n){c[i]+=v;if(c[i]>=mod)c[i]%=mod;i+=lowbit(i);}}int main(){//ios::sync_with_stdio(false); int i,j;while(scanf("%d",&n)!=EOF){memset(b,0,sizeof(b));memset(c,0,sizeof(c));for(i=1;i<=n;i++){scanf("%d",&a[i].v); a[i].id=i;}sort(a+1,a+n+1);b[a[1].id]=1;for(i=2;i<=n;i++) //离散化{if(a[i].v!=a[i-1].v)b[a[i].id]=i;else b[a[i].id]=b[a[i-1].id];}for(i=1;i<=n;i++)  //核心点也是难理解的地方{t[i]=sum(b[i]);add(b[i],t[i]+1);}printf("%d\n",sum(n));}return 0;} 


阅读全文
1 0