zoukankan      html  css  js  c++  java
  • 选举 [数据结构优化dp]

    选举


    Descriptionmathcal{Description}

    在这里插入图片描述


    Solutionmathcal{Solution}

    F[i]i,F[i]=max{F[j]+1         (sumi>sumj)F[j]                (sumi=sumj)F[j]1         (sumi<sumj)设F[i]表示前i个选民的最优答案,得到\ F[i]=maxegin{cases} F[j]+1 (sum_i>sum_j) \ F[j] (sum_i=sum_j)\ F[j]-1 (sum_i<sum_j) end{cases}
    复杂度 O(N2)O(N^2).

    :优化部分:
    sumn{sum_n} 为下标建立 权值线段树,
    线段树的每个叶子节点保存 sumi=color{blue}{满足sum_i=叶子下标} 的每个 ii 位置上的 F[]color{red}{最大F[]值}.

    则可以直接查询比当前 sumisum_i小的,大的,相等的 最大的 F[j]F[j], O(logn)O(logn) 实现单次转移.

    每次 i++i++ , iL+1i-L+1 可以被合法转移, iR+1i-R+1 不能被合法转移, 于是在线段树中删除掉其对应的 dpdp 值.


    bug
    Codemathcal{Code}

    #include<bits/stdc++.h>
    #define reg register
    typedef std::pair<int, int> pr;
    
    int read(){
            char c;
            int s = 0, flag = 1;
            while((c=getchar()) && !isdigit(c))
                    if(c == '-'){ flag = -1, c = getchar(); break ; }
            while(isdigit(c)) s = s*10 + c-'0', c = getchar();
            return s * flag;
    }
    
    const int maxn = 1e6 + 6;
    const int inf = 0x3f3f3f3f;
    
    int N;
    int L;
    int R;
    int Lim;
    int A[maxn];
    int F[maxn];
    int sum[maxn];
    
    struct Node{
            std::priority_queue <pr> que;
            int l, r, max_v;
    } T[maxn*4];
    
    void Build(int k, int l, int r){ //
            T[k].l = l, T[k].r = r;
            if(l == r){ T[k].max_v = -inf; return ; }
            int mid = l+r >> 1;
            Build(k<<1, l, mid), Build(k<<1|1, mid+1, r);
            T[k].max_v = -inf; 
    }
    
    void Modify(int k, int id){ //
            int l = T[k].l, r = T[k].r;
            if(l == r){ 
                    T[k].que.push(pr(F[id], id)); 
                    T[k].max_v = T[k].que.top().first;
                    return ;
            }
            int mid = l+r >> 1;
            if(sum[id] <= mid) Modify(k<<1, id);
            else Modify(k<<1|1, id);
            T[k].max_v = std::max(T[k<<1].max_v, T[k<<1|1].max_v);
    }
    
    void Del(int k, int id){ //
            int l = T[k].l, r = T[k].r;
            if(l == r){
                    while(!T[k].que.empty() && T[k].que.top().second < Lim) T[k].que.pop();
                    if(T[k].que.empty()) T[k].max_v = -inf;
                    else T[k].max_v = T[k].que.top().first;
                    return ;
            }
            int mid = l+r >> 1;
            if(sum[id] <= mid) Del(k<<1, id);
            else Del(k<<1|1, id);
            T[k].max_v = std::max(T[k<<1].max_v, T[k<<1|1].max_v);
    }
    
    int Query(int k, int Ql, int Qr){ //
            int l = T[k].l, r = T[k].r;
            if(Ql <= l && r <= Qr) return T[k].max_v;
            int mid = l+r >> 1;
            if(mid+1 <= Ql) return Query(k<<1|1, Ql, Qr);
            else if(mid >= Qr) return Query(k<<1, Ql, Qr); 
            return std::max(Query(k<<1, Ql, Qr), Query(k<<1|1, Ql, Qr));
    }
    
    int main(){
            freopen("election.in", "r", stdin);
            freopen("election.out", "w", stdout);
            N = read(), L = read(), R = read();
            for(reg int i = 1; i <= N; i ++) A[i] = read(), sum[i] = sum[i-1] + A[i];
            for(reg int i = 0; i <= N; i ++) sum[i] += N;
            memset(F, -0x3f, sizeof F); F[0] = 0;
            Build(1, 0, N<<1); Modify(1, 0);
            for(reg int i = L; i <= N; i ++){
                    Lim = std::max(i-R, 0); 
                    F[i] = std::max(F[i], Query(1, 0, std::max(0, sum[i]-1)) + 1);
                    F[i] = std::max(F[i], Query(1, sum[i], sum[i]));
                    F[i] = std::max(F[i], Query(1, std::min(sum[i]+1, N<<1), N<<1) - 1); 
                    if(i-R >= 1) Del(1, i-R);
                    if(i-L >= 0) Modify(1, i-L);
            }
            printf("%d
    ", F[N]);
            return 0;
    }
    
    /*
    Bug List:
    1. Build -> push_up
    2. For(int i = 1; i <= N; i ++)  <<-- For(int i = L; i <= N; i ++)
    */
    
    
    
  • 相关阅读:
    使用createDocumentFragment的渲染数据(节省性能)
    面向对象写法模板
    面向对象this指向
    js 3D图片叠加旋转切换
    三列布局-中间固定俩边自适应-和两边固定中间自适应布局
    游戏中抽奖的算法
    c++11:lambda表达式
    c++11:模板
    c++11:左值、右值
    游戏服务器语言之争
  • 原文地址:https://www.cnblogs.com/zbr162/p/11822593.html
Copyright © 2011-2022 走看看