hdu 2227 树状数组+dp

题意是求一个数列的不递减的子序列的个数;

很显然,如果只用dp来做的话时间是O(n*n) 因为dp【i】为前i个数可能的方案,则状态转移方程为dp【i】=sum(dp【j】,j<i&&num【j】<=num【i】)+1 对小数据坑定能过 但大数据就超时了,这里用到了树状数组来优化;

先对num按数来进行排序,(这道题因为数据较大  用到了离散化) 因为更新是是按原序更新的,及i之前的num【j】一定比num【i】小,维护了不递减的原则,更新是从mark【i】(表示原序列i在排序后的位置)开始更新 这就维护了子序列的原则,最后求和就行;

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;

#define mod 1000000007

struct node
{
    int value;
    int ii;
}num[100010];
int cmp(node a,node b)
{
    return a.value<b.value;
}
int cont[100010],n;
int update(int a,int b)
{
    for(int i=a;i<=n;i+=(i&-i))
    {
        cont[i]+=b;
        cont[i]%=mod;
    }    
    return 0;
}
int find(int a)
{
    int s=0;
    for(int i=a;i>=1;i-=(i&-i))
    {
        s+=cont[i];
        s%=mod;
    }    
    return s;
}
int main()
{
    int i,j;
    int mark[100010];
    int dp[100010];
    while(~scanf("%d",&n))
    {
        for(i=1;i<=n;i++)
        {
            scanf("%d",&num[i].value);
            num[i].ii=i;
        }
        sort(num+1,num+1+n,cmp);
        int k=-1,t=0;
        for(i=1;i<=n;i++)
        {
            if(num[i].value!=k)
            {
                ++t;
                k=num[i].value;
            }
            mark[num[i].ii]=t;
        }
        memset(cont,0,sizeof(cont));
        for(i=1;i<=n;i++)
        {
            dp[i]=find(mark[i]);
            dp[i]%=mod;
            update(mark[i],dp[i]+1);
        }
        printf("%d\n",find(n));
    }
    return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值