zoukankan      html  css  js  c++  java
  • HDU 2227 Find the nondecreasing subsequences

    树状数组+dp因为今天复习离散化于是手贱加了个离散化

    题目大意

    意思是给你一段序列,求里面的最长不下降子序列的个数。

    dp思想

    这道题的dp方程非常的好推,看完题目的第一眼就已经推出了方程

    设dp[i]表示以当前点为终点的序列方案。所以方程是

    [dp[i] += (i>j&&a[i]ge a[j])? dp[j]:0\ ans=sum_{i=1}^{n}(dp[i]+1) ]

    但是一看这种方法就是(n^2)的复杂度,明显过不了,那怎么办呢?

    优化

    我们知道,我们最后求得一定是一个前缀和的形式,所以这个树状数组可以做的很好。

    我们先将原数组从小到大排个序,然后寻找它的下标。

    为什么从小到大呢?因为从小到大的话我们求得一定是不下降子序列,那么决定答案的就是原位置的下标。

    我们可以二分查找它的下标,那么在他下标之前的前缀和一定就是总的方案数。

    然后在查询的前缀合里加1,就是答案。

    不理解?举个例子。

    排序前: 1 2 5 4 3
    排序后: 1 2 3 4 5
    数组下标: 1 2 5 4 3
    首先第一个值是1,它得下标是1,前缀是0,所以方案数是1
    第二个值2,下标二,前缀和1,方案数2
    下个值3,下标是3,位置是5,前缀和是3,方案数4
    下个值4,下标是4,位置是4,前缀和是4,方案数是5
    下个值5,下标是5,位置是3,前缀和是3,方案数是4

    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define LL long long
    using namespace std;
    const int mod = 1000000007;
    int c[100001];
    int n;
    int b[100001],cnt;
    LL tree[100001];
    int a[100001];
    bool cmp(int x,int y) {
    	return x<y;
    }
    int lowbit(int k) {
    	return k&(-k);
    }
    void add(int k,int val) {
    	while(k<=n) {
    		tree[k]+=val;
    		k+=lowbit(k);
    	}
    }
    int ask(int k) {
    	int ans=0;
    	while(k!=0) {
    		ans = (ans+tree[k])%mod ;
    		k-=lowbit(k);
    	}
    	return ans%mod;
    }
    int main() {
    	while(scanf("%d",&n)!=EOF) {
    		memset(a,0,sizeof(a));
    		memset(b,0,sizeof(b));
    		memset(c,0,sizeof(c));
    		memset(tree,0,sizeof(tree));
    		cnt=0;
    		for(int i=1; i<=n; i++) scanf("%d",&a[i]),b[i]=a[i];
    		sort(b+1,b+1+n,cmp);
    		for(int i=1; i<=n; i++) if(b[i]!=b[cnt])b[++cnt]=b[i];
    		for(int i=1; i<=n; i++)a[i]=lower_bound(b+1,b+1+cnt,a[i])-b;
    		for(int i=1; i<=n; i++)c[i]=a[i];
    		sort(a+1,a+1+n,cmp);
    		for(int i=1; i<=n; i++) {
    			int id=lower_bound(a+1,a+1+n,c[i])-a;
    			add(id,ask(id)+1);
    		}
    		printf("%d
    ",ask(n));
    	}
    }
    
  • 相关阅读:
    假期十一
    假期十
    假期九
    假期八
    假期七
    假期六
    假期五
    假期四
    2020.02.11
    2020.02.10
  • 原文地址:https://www.cnblogs.com/ifmyt/p/9713705.html
Copyright © 2011-2022 走看看