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;
}
时间: 2024-10-24 22:04:36

hdu 2227 树状数组+dp的相关文章

hdu 3450(树状数组+dp)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3450 Counting Sequences Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/65536 K (Java/Others) Total Submission(s): 1815    Accepted Submission(s): 618 Problem Description For a set of seque

hdu 3030 Increasing Speed Limits (离散化+树状数组+DP思想)

Increasing Speed Limits Time Limit: 2000/10000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 481    Accepted Submission(s): 245 Problem Description You were driving along a highway when you got caught by the road p

hdu 3333 树状数组+离线处理

http://acm.hdu.edu.cn/showproblem.php?pid=3333 不错的题,想了很久不知道怎么处理,而且答案没看懂,然后找个例子模拟下别人的代码马上懂了---以后看不懂的话就拿个例子模拟下别人的代码 举个例子:1 3 3 5 3 5 查询 a, 2 4 b, 2 5 最初是这么想的:对于a查询,倘若把第二个数第三个数变成1个3,那么到b查询,又出现了两个3,再做处理似乎还是O(n),而且如果先出现2,5查询,后出现2,4查询,那么还需要把删除的数补回来.....o(╯

Hdu 3887树状数组+模拟栈

题目链接 Counting Offspring Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1757    Accepted Submission(s): 582 Problem Description You are given a tree, it’s root is p, and the node is numbered fr

HDU 1754 树状数组 解法

mnesia在频繁操作数据的过程可能会报错:** WARNING ** Mnesia is overloaded: {dump_log, write_threshold},可以看出,mnesia应该是过载了.这个警告在mnesia dump操作会发生这个问题,表类型为disc_only_copies .disc_copies都可能会发生. 如何重现这个问题,例子的场景是多个进程同时在不断地mnesia:dirty_write/2 mnesia过载分析 1.抛出警告是在mnesia 增加dump

HDU 1166(树状数组)

用树状数组把HDU1166再写了一次  感觉树状数组简洁 1 #include <cstdio> 2 #include <iostream> 3 #include <string.h> 4 using namespace std; 5 int c[50002],lv[50002],n; 6 int lowbit(int x){return x&(-x);} 7 int sum(int b){ 8 int sum=0; 9 while(b>0){ 10 su

hdu 4368 树状数组 离线维护

http://acm.hdu.edu.cn/showproblem.php?pid=4638 Problem Description There are n men ,every man has an ID(1..n).their ID is unique. Whose ID is i and i-1 are friends, Whose ID is i and i+1 are friends. These n men stand in line. Now we select an interv

hdu4455之树状数组+DP

Substrings Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1571    Accepted Submission(s): 459 Problem Description XXX has an array of length n. XXX wants to know that, for a given w, what is

hdu 4630 树状数组+离线操作+GCD

http://acm.hdu.edu.cn/showproblem.php?pid=4630 重新认识了树状数组. 首先要记住那个树形的图,然后+或-lowbit(i)是自己根据具体问题设定的,不要死于+或者-, 树状数组的特点: 1.+lowbit(i)可以到达包含结点i的上一层父节点    所以用于值的更改 2.-lowbit(i)可以到达不包含i所代表区间的上一层父节点  所以用于值的求和---每个不相交的段加起来 3.C[i]的含义也是根据具体问题去做设定的,但是c[i]覆盖了a[i-2