zoukankan      html  css  js  c++  java
  • P1970 花匠 [权值线段树优化dp, NOIp2003, Y]

    花匠


    Descriptionmathcal{Description}
    见标题链接.


    最初想法
    既然有两种情况, 就一个个解决吧, 先第二种情况,
    F[i,0/1]F[i,0/1] 表示前 ii 个能够选择出的最多花盆, 00 表示ii位置作为 低点, 11 表示ii位置作为 高点.
    初值 F[i,1]=1,F[i,0]=0F[i,1]=1,F[i,0]=0 .

    H[j]>H[i]:  F[i,0]=max(F[j,1]+1)H[j]<H[i]:  F[i,1]=max(F[j,0]+1)H[j]>H[i]: F[i,0]=max(F[j,1]+1) \ H[j]<H[i]: F[i,1]=max(F[j,0]+1)

    Ans=maxi[1,N](F[i,1])Ans=max_{i∈[1,N]}(F[i,1])

    先提交一下 O(N2)O(N^2) 暴力, 检验正确性, 结果 40pts40pts 爆炸.

    原来题目要求的偶数位为 最低点/最高点 可以当做选出最后一个盆栽啊!

    于是
    初值 F[i,1]=F[i,0]=1F[i,1]=F[i,0]=1,
    Ans=maxi[1,N](F[i,1],F[i,0])Ans=max_{i∈[1,N]}(F[i,1],F[i,0])
    也不用一个一个情况讨论了, 因为相当于求的是 最长波浪 了.

    改了之后就有 80pts80pts 了, Luogu跑的真快 .


    正解部分

    使用权值线段树优化为 O(NlogN)O(NlogN) 即可.

    #include<bits/stdc++.h>
    #define reg register
    
    const int maxn = 100005;
    
    int N;
    int Ans;
    int H[maxn];
    int F[maxn][2];
    
    struct Node{ int l, r, max_v; } T[2][(int)(4e6)+5];
    
    void Build(int k, int l, int r){
            T[0][k].l = T[1][k].l = l, T[0][k].r = T[1][k].r = r;
            if(l == r){
                    T[1][k].max_v = T[0][k].max_v = 0;
                    return ;
            }
            int mid = l+r >> 1;
            Build(k<<1, l, mid), Build(k<<1|1, mid+1, r);
            T[0][k].max_v = T[1][k].max_v = 0;
    }
    
    void Modify(int k, int pos, int val, int opt){
            int l = T[opt][k].l, r = T[opt][k].r;
            if(l == r){ T[opt][k].max_v = val; return ; }
            int mid = l+r >> 1;
            if(pos <= mid) Modify(k<<1, pos, val, opt);
            else Modify(k<<1|1, pos, val, opt);
            T[opt][k].max_v = std::max(T[opt][k<<1].max_v, T[opt][k<<1|1].max_v);
    }
    
    int Query(int k, int Ql, int Qr, int opt){
            if(Ql > Qr) return 0;
            int l = T[opt][k].l, r = T[opt][k].r;
            if(Ql <= l && r <= Qr) return T[opt][k].max_v;
            int mid = l+r >> 1;
            if(Qr <= mid) return Query(k<<1, Ql, Qr, opt);
            else if(Ql >= mid+1) return Query(k<<1|1, Ql, Qr, opt);
            return std::max(Query(k<<1, Ql, Qr, opt), Query(k<<1|1, Ql, Qr, opt));
    }
    
    int main(){
            scanf("%d", &N);
            int Lim = 1;
            for(reg int i = 1; i <= N; i ++) scanf("%d", &H[i]), Lim = std::max(H[i], Lim);
            Build(1, 0, Lim);
            for(reg int i = 1; i <= N; i ++){
                    F[i][0] = Query(1, 0, H[i]-1, 1) + 1;
                    F[i][1] = Query(1, H[i]+1, Lim, 0) + 1;
                    Modify(1, H[i], F[i][0], 0);
                    Modify(1, H[i], F[i][1], 1);
                    Ans = std::max(Ans, F[i][1]);
                    Ans = std::max(Ans, F[i][0]);
            }
            printf("%d
    ", Ans);
            return 0;
    }
    
    
  • 相关阅读:
    java常见异常
    实现两个整数变量交换
    java抽象类与接口
    Java内部类用法
    单例模式
    easyUI下拉列表点击事件的使用
    Java中使用HttpRequest获取用户真实IP地址端口
    js-easyUI格式化时间
    1124
    ACM算法
  • 原文地址:https://www.cnblogs.com/zbr162/p/11822582.html
Copyright © 2011-2022 走看看