zoukankan      html  css  js  c++  java
  • 【BZOJ】4709: [Jsoi2011]柠檬

    4709: [Jsoi2011]柠檬

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 779  Solved: 310
    [Submit][Status][Discuss]

    Description

    Flute 很喜欢柠檬。它准备了一串用树枝串起来的贝壳,打算用一种魔法把贝壳变成柠檬。贝壳一共有 N (1 ≤ N
     ≤ 100,000) 只,按顺序串在树枝上。为了方便,我们从左到右给贝壳编号 1..N。每只贝壳的大小不一定相同,
    贝壳 i 的大小为 si(1 ≤ si ≤10,000)。变柠檬的魔法要求,Flute 每次从树枝一端取下一小段连续的贝壳,并
    选择一种贝壳的大小 s0。如果 这一小段贝壳中 大小为 s0 的贝壳有 t 只,那么魔法可以把这一小段贝壳变成 s
    0t^2 只柠檬。Flute 可以取任意多次贝壳,直到树枝上的贝壳被全部取完。各个小段中,Flute 选择的贝壳大小 s
    0 可以不同。而最终 Flute 得到的柠檬数,就是所有小段柠檬数的总和。Flute 想知道,它最多能用这一串贝壳
    变出多少柠檬。请你帮忙解决这个问题。
     

    Input

    第 1 行:一个整数,表示 N。
    第 2 .. N + 1 行:每行一个整数,第 i + 1 行表示 si。
     

    Output

    仅一个整数,表示 Flute 最多能得到的柠檬数。
     

    Sample Input

    5
    2
    2
    5
    2
    3

    Sample Output

    21
    //Flute 先从左端取下 4 只贝壳,它们的大小为 2, 2, 5, 2。选择 s0 = 2,那么这一段
    里有 3 只大小为 s0 的贝壳,通过魔法可以得到 2×3^2 = 18 只柠檬。再从右端取下最后一
    只贝壳,通过魔法可以得到 1×3^1 = 3 只柠檬。总共可以得到 18 + 3 = 21 只柠檬。没有
    比这更优的方案了。

    HINT

     

    Source

     
    [Submit][Status][Discuss]


    HOME Back

    还没有学会斜率优化...可以直接单调栈,参考neither_nor的博客,在代码里面写了一点注释:

    #include<iostream>
    #include<cstdio>
    #include<vector>
    #define ll long long
    using namespace std;
    
    int n, s, cnt[10005], pre[100005], color[100005];
    vector < int > stk[10005];
    ll f[100005];
    
    ll count ( int x, int num ) {
        return f[x-1] + (ll)color[x] * num * num;
    }
    
    int find ( int x, int y ) {//x,y是需要判断的下标,find的是x超过y的位置 
        int l = 1, r = n, res = n + 1;
        while ( l <= r ) {
            int mid = ( l + r ) >> 1;
            if ( count ( x, mid - pre[x] + 1 ) >= count ( y, mid - pre[y] + 1 ) ) {//mid查找的是当前颜色的第几个入栈时间 
                res = mid; r = mid - 1;
            } else l = mid + 1;
        }
        return res;
    }
    
    int main ( ) {
        scanf ( "%d", &n );
        for ( int i = 1; i <= n; i ++ ) {
            scanf ( "%d", &s );
            cnt[s] ++;
            color[i] = s;
            pre[i] = cnt[s];
            while ( stk[s].size ( ) >= 2 && find ( stk[s][stk[s].size ( ) - 2], stk[s][stk[s].size ( ) - 1] ) <= 
                    find ( stk[s][stk[s].size ( ) - 1], i ) ) stk[s].pop_back ( );//防止第二个元素超过栈顶的时间比栈顶超过i的时间早,此时栈顶没用 
            stk[s].push_back ( i );//先推入防止最后从0更新 
            while ( stk[s].size ( ) >= 2 && find ( stk[s][stk[s].size ( ) - 2], stk[s][stk[s].size ( ) - 1] ) <= 
                    pre[i] ) stk[s].pop_back ( );//i是这种颜色第pre[i]个入栈的 //第二个元素超过栈顶的时间比第一个元素进入的时间早,栈顶就没用了 
            f[i] = count ( stk[s][stk[s].size ( ) - 1], pre[i] - pre[stk[s][stk[s].size ( ) - 1]] + 1 );
        }
        ll ans = 0;
        for ( int i = 1; i <= n; i ++ )
            ans = max ( ans, f[i] );
        printf ( "%lld
    ", ans );
        return 0;
    }
  • 相关阅读:
    触摸屏网站开发系列(一)-ios web App应用程序(ios meta)
    jQuery Mobile 入门教程
    html的视频插件 (转)
    网页布局流式布局
    2.05-random-uesr-proxy
    2.04-proxy-handler
    2.03-handler_openner
    2.02-request_header_two
    2.01-request_header
    1.03-get_params2
  • 原文地址:https://www.cnblogs.com/wans-caesar-02111007/p/9477413.html
Copyright © 2011-2022 走看看