• UVALive 6915 Leveling Ground 倍增RMQ


    Leveling Ground

    题目连接:

    https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4925

    Description

    It is important to first level the ground before you build anything on top of it (e.g., new house, shed,
    swimming pool, driveway, etc.), especially when there are hills on the land, otherwise whatever you
    built will not be stable. In case you don’t understand, “leveling the ground” means making the ground
    flat and even (having the same height). In this problem, you are given a land description and the
    length of land — M — that you want to level; your task is to determine the minimum amount of land
    you should dispose in order to have a level land of length M. Note that in this problem you are only
    allowed to dispose land, not filling it.
    The total length of the given land will be N, and the land will be encoded with the following format:
    (1) / means ascending slope (disposing an ascending slope cost 0.5),
    (2) means descending slope (disposing a descending slope cost 0.5),
    (3) means flat (disposing a flat land cost 0),
    (4) . means full land (disposing a full land cost 1).
    Note that the input will only describe the land’s surface, thus (4) will not appear in any input. Also
    note that (1) and (2) are not level.
    For example, consider the following input.
    Input : //_//_\_/////
    The input corresponds to the following land (which length is 31).
    __ /_ __
    /.._/... /.. _
    Land : /.......... ___ /...._
    /.
    ............_/.../...........
    ...............................
    Index : 1234567890123456789012345678901
    Supposed we want to level a land of length M = 7, and for some reasons, we choose the land we
    want to level to be at index [11, 17]. Recall that you are only allowed to dispose land, thus if you want
    to level the land at [11, 17], you should level it such that the height is equal to the height of land at
    index 14 (because it is the lowest point). In the following figure, ‘’ (stars) mark the land which should
    be disposed.
    __ /_ __ __ /_ __
    /.._/...
    /.. _ /.._/...| /.. _
    /.........** **_ /...._
    /. /.........| _ /...._/.
    ..........*******./........... ..........|
    ____|./...........
    ............................... ...............................
    Index : 1234567890123456789012345678901 1234567890123456789012345678901
    If you observe, there are 12 stars in the left figure, they are:
    • 1 ascending slope (at index: 15),
    • 3 descending slopes (at indexes: 11, 12, and 13),
    • 3 flat lands (at indexes: 14, 16, and 17), and
    • 5 full lands (2 at index 11, 1 at index 12, 1 at index 16, and another 1 at index 17).
    Therefore, the cost of leveling [11, 17] is: 1 * 0.5 + 3 * 0.5 + 3 * 0 + 5 * 1 = 7.
    In this example, [11, 17] is not the best choice, you can do better.

    Input

    The first line of input contains T (T ≤ 50) denoting the number of cases. Each case begins with two
    integers N and M (1 ≤ M ≤ N ≤ 1, 000, 000) denoting the total length of the land and the length of the
    land which should be leveled respectively. The following line contains a string of length N describing
    the land’s surface. The string will only contain character ‘/’, ‘’, or ‘ ’, as described in the problem
    statement.

    Output

    For each case, output ‘Case #X: Y ’, where X is the case number starts from 1 and Y is the minimum
    amount of land which should be disposed to achieve a level land which length is M for that particular
    case. Output this number with exactly one digit after the decimal point.
    Explanation for 1st sample case:
    This is the same case as the example in the problem statement. The minimum amount of land
    which you should dispose is 3.5. You can achieve this by leveling lands at [25, 31].
    __ /_ __ __ /_ __
    /.._/... /.. _ /.._/... /..* *
    Land : /.......... ___ /....___/. /.......... ___ /...*******
    ............_/.../........... ............_/.../...........
    ............................... ...............................
    Index : 1234567890123456789012345678901 1234567890123456789012345678901
    You will dispose: 1 ascending slope (at index 30), 2 descending slopes (at index 15 and 16), 4 flat
    lands (at index 27, 28, 29, and 31), and 2 full lands (at index 15 and 31). Therefore the total cost will
    be: 1 * 0.5 + 2 * 0.5 + 4 * 0 + 2 * 1 = 3.5.
    Explanation for 2nd sample case:
    If you level the land at [3, 6] or [4, 7], you don’t need to dispose any land as they are already level
    (have the same height).
    Explanation for 3rd sample case:
    Level the land at [8, 11], and you only need to dispose 1 ascending slope and 1 descending slope.

    Sample Input

    4
    31 7
    //_//_\_/////
    10 4
    //
    ____/
    12 4
    \///_
    12 1
    //////

    Sample Output

    Case #1: 3.5
    Case #2: 0.0
    Case #3: 1.0
    Case #4: 0.5

    Hint

    题意

    给你一个类似山峰的东西,你可以使得一个连续的m长度的山峰变成这一块的最低值。

    然后问你最小的花费是多少。

    (题意还是比较烦的,自己读读吧,我说不是很清楚……

    题解:

    考虑滑块,我们维护区间和,和区间最小值,那么花费就是区间和减去区间最小值乘以这个区间的大小就好了。

    然后我们类似滑块去维护就好了。

    O(n)就用单调队列去维护最小值,前缀和维护区间和就行了。

    nlogn的做法就相当多了……

    代码

    #include<bits/stdc++.h>
    #define two(x) (1<<(x))
    using namespace std;
    const int maxn = 1e6+7;
    int a[maxn],b[maxn];
    char s[maxn];
    int mm[maxn];
    int c[maxn][21];
    int two[maxn];
    void initrmp(int n)
    {
        mm[0]=-1;
        for(int i=1;i<=n;i++){
            mm[i]=((i&(i-1))==0)?mm[i-1]+1:mm[i-1];
        }
    }
    
    int query(int l,int r){
        int k = mm[r-l+1];
        return min(c[l][k],c[r-(1<<k)+1][k]);
    }
    
    int cas = 0;
    void solve(){
        int n,m;
        scanf("%d%d",&n,&m);
        scanf("%s",s+1);
        initrmp(n);
        int now = 0;
        for(int i=1;i<=n;i++){
            if(s[i]=='/')a[i]=now,b[i]=1,now++;
            if(s[i]=='\')now--,a[i]=now,b[i]=1;
            if(s[i]=='_')a[i]=now,b[i]=0;
            c[i][0]=a[i];
        }
        for(int j=1;j<21;j++) for(int i = 1 ; i + ( 1 << j ) - 1 <= n ; ++ i) c[i][j]=min( c[i][j-1] , c[i + two(j-1)][j-1] );
        long long sum = 0;
        long long sum2 = 0;
        for(int i=1;i<=m;i++){
            sum+=1LL*a[i];
            sum2+=1LL*b[i];
    
        }
        double Ans = 1e9;
        Ans = 1.0*sum+0.5*sum2-1.0*m*query(1,m);
        for(int i=m+1;i<=n;i++){
            sum+=1LL*a[i]-1LL*a[i-m];
            sum2+=1LL*b[i]-1LL*b[i-m];
            Ans=min(Ans,1.0*sum+0.5*sum2-1.0*m*query(i-m+1,i));
        }
        printf("Case #%d: %.1f
    ",++cas,Ans);
    }
    int main(){
        //freopen("1.txt","r",stdin);
        int t;
        scanf("%d",&t);
        while(t--)solve();
        return 0;
    }
  • 相关阅读:
    白盒测试的特点
    什么是黑盒测试
    黑盒测试优缺点
    单元测试
    孤立的测试策略
    自顶向下的单元测试策略
    自底向上的单元测试策略
    tabbedApliction
    redis的key对应mysql数据表设计
    达内javase_day1笔记
  • 原文地址:https://www.cnblogs.com/qscqesze/p/5734158.html
Copyright © 2020-2023  润新知