zoukankan      html  css  js  c++  java
  • 洛谷 P2008 大朋友的数字

    DP,动态规划   树状数组   最长不下降子序列

    by  GeneralLiu

    题目

    就是说给一串由 0~9 组成的序列

    求 以 i (1~n) 结尾 的 最长不下降子序列 的 和

    (最长不下降子序列不唯一时选编号字典序最小的)

    两步

    1 求最长不下降子序列

    2 求 步骤1 的和

    1

    O(n^2) 暴力不必说 (因为数字只有 0~9 十个, 即10*n, 所以就是 O(n)啊)

    O(n logn) 树状数组 log10≈3.几,即3*n 也可以算 O(n)啊;

    对于 数值x 查询 以0~x结尾的 最长不下降子序列 长度 

    所得长度 +1 即为所求

    用 树状数组 维护

    !!!!

    树状数组没有 0 啊

    那就每个数 查询和更新 都加一

    因为这个我卡了 TLE 当时相当不解 

    2

    再开一个数组保存序列和

    在步骤1中一起维护即可

    详见代码 query() 和 update()

    代码

    #include<bits/stdc++.h>
    using namespace std;
    #define low k&-k
    int ret,l,n,tree[10010],s[10010];
    void query(int k){ //查询 
        ret=s[k],l=tree[k]; //ret为序列和 l为长度 两个全局变量 
        for(k-=low;k;k-=low)
            if(l<tree[k])//因为要保证字典序 所以 == 时 答案不改
                l=tree[k],ret=s[k]; //长度更改时 序列和才会更改 
    }
    void update(int k){ //更新 
        for(;k<=10;k+=low)
            if(tree[k]<l) //因为要保证字典序 所以 == 时 不作修改 
                tree[k]=l,s[k]=ret; //长度更新时 序列和才会更新 
    }
    int main(){
        scanf("%d",&n);
        for(int v,i=1;i<=n;i++){
            scanf("%d",&v);
            query(v+1); //树状数组没有 0 要统一 +1  
            ret+=v; 
            l++;//长度再加上 本身 
            printf("%d ",ret);
            update(v+1);
        }
        return 0;
    }/*5
    0 2 5 3 4*/
  • 相关阅读:
    __get__,__set__,__delete__
    __getattr__,__setattr__,__delattr__
    json ,pickle
    @property
    类的封装
    super
    继承顺序
    派生组合示例
    类的派生,组合
    class 属性查找
  • 原文地址:https://www.cnblogs.com/1227xq/p/6906790.html
Copyright © 2011-2022 走看看