zoukankan      html  css  js  c++  java
  • zoj 3349 dp + 线段树优化

    题目:给出一个序列,找出一个最长的子序列,相邻的两个数的差在d以内。

     1 /*
     2 线段树优化dp
     3 dp[i]表示前i个数的最长为多少,则dp[i]=max(dp[j]+1) abs(a[i]-a[j])<=d
     4 复杂度为O(n ^ 2)
     5 利用线段树优化,线段树保存区间最大值。离散化后便可求出,还要注意 对于叶子节点保存的即为dp的值,每次更改即可,开始一直累加。。。。。
     6 */
     7 #include <iostream>
     8 #include <cstdio>
     9 #include <cstring>
    10 #include <cmath>
    11 #include <algorithm>
    12 
    13 using namespace std;
    14 #define lson l,m,rt<<1
    15 #define rson m + 1, r, rt<<1|1
    16 const int maxn = 1e5 + 5;
    17 int s[maxn];
    18 int n, d;
    19 int san[maxn], tot;
    20 int sum[maxn << 2];
    21 void pushUp(int rt){
    22     sum[rt] = max(sum[rt<<1], sum[rt<<1|1]);
    23 }
    24 void update(int pos, int c, int l, int r, int rt){
    25     if (l == r){
    26         sum[rt] = c;//注意
    27         return ;
    28     }
    29     int m = (l + r) >> 1;
    30     if (pos <= m) update(pos, c, lson);
    31     else update(pos, c, rson);
    32     pushUp(rt);
    33 }
    34 int query(int L, int R, int l, int r, int rt){
    35     if (L <= l && R >= r){
    36         return sum[rt];
    37     }
    38     int m = (l + r) >> 1;
    39     int ret = 0;
    40     if (L <= m) ret = query(L, R, lson);
    41     if (R > m) ret = max(ret, query(L, R, rson));
    42     return ret;
    43 }
    44 int main(){
    45     while (~scanf("%d%d", &n, &d)){
    46         tot = 0;
    47         for (int  i = 1; i <= n; ++i){
    48             scanf("%d", &s[i]);
    49             san[tot++] = s[i];
    50         }
    51         sort(san, san + tot);
    52         tot = unique(san, san + tot) - san;
    53 
    54         memset(sum, 0, sizeof(sum));
    55         int ans = 0;
    56         for (int i = 1; i <= n; ++i){
    57             int pos = lower_bound(san, san + tot, s[i]) - san + 1;
    58             int l = lower_bound(san, san + tot, s[i] - d) - san + 1;
    59             int r = upper_bound(san, san + tot, s[i] + d) - san;
    60             int que = query(l, r, 1, tot, 1) + 1;
    61             //cout << " l = " << l << " r = " << r << endl;
    62             ans = max(ans, que);
    63             //cout << " ans = " << ans << endl;
    64             update(pos, que, 1, tot, 1);
    65         }
    66         printf("%d
    ", ans);
    67     }
    68     return 0;
    69 }
  • 相关阅读:
    基础 之 数组
    记录某个进程任意的采集时间内,top 10 的cpu和内存值的平均和求和
    8、广度优先搜索
    7、散列表
    计算机网络之从接入网到互联网
    计算机网络
    15、python之导入模块
    14、函数之匿名函数(lambda)
    13、python中的函数(闭包与装饰器)
    6、快速排序
  • 原文地址:https://www.cnblogs.com/Missa/p/3416569.html
Copyright © 2011-2022 走看看