UVALive 6915 J

思路: 简单模拟下。从左向右扫描一次,求出挖出该区间空地的花费,并取个最小值即可。

  至于怎么求区间内的高度最小值,就用线段树就好了。

#include <bits/stdc++.h>
#define PB push_back
#define MP make_pair
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
#define PI acos((double)-1)
#define E exp(double(1))
#define K 1000000+9
struct node1
{
    int h,kind;
}mp[K];
int n,m;
char ss[K];
struct node
{
    int mi;
    int left,right;
}tree[4*K];
int build(int id,int l,int r)
{
    tree[id].left=l;tree[id].right=r;
    if(l==r)
        tree[id].mi=mp[l].h;
    else
    {
        build(2*id,l,(l+r)/2);
        build(2*id+1,(l+r)/2+1,r);
        tree[id].mi=min(tree[2*id].mi,tree[2*id+1].mi);
    }
    return 0;
}
int query(int id,int l,int r)
{
    if(l==tree[id].left && r==tree[id].right)
        return tree[id].mi;
    int mid=(tree[id].left+tree[id].right)>>1;
    int ret=0x3f3f3f3f;
    if(r<=mid)
        ret=min(ret,query(id*2,l,r));
    else if(l>=mid+1)
        ret=min(ret,query(id*2+1,l,r));
    else
    {
        int a,b;
        a=query(id<<1,l,mid);
        b=query((id<<1)+1,mid+1,r);
        return min(a,b);
    }
    return ret;
}
double get_ans(int x,int mi)
{
    double ans=0;
    ans+=mp[x].h-mi;
    ans+=mp[x].kind==0?0:0.5;
    return ans;
}
int main(void)
{
    int t,cs=1;cin>>t;
    while(t--)
    {
        double ans,sum=0;
        scanf("%d%d%s",&n,&m,&ss[1]);
        mp[0].h=1;
        for(int i=1,ls=0;i<=n;i++)
        {
            mp[i].h=mp[i-1].h+ls;
            if(ss[i]=='_')ls=0,mp[i].kind=0;
            else if(ss[i]=='/')ls=1,mp[i].kind=1;
            else if(ss[i]=='\')ls=0,mp[i].kind=2,mp[i].h--;
            //printf("%d : %d
",i,mp[i].h);
        }
        build(1,1,n);
        for(int i=1,mi=query(1,1,m);i<=m;i++)
            sum+=get_ans(i,mi);
        ans=sum;
        for(int i=m+1,ls=query(1,1,m);i<=n;i++)
        {
            int mi=query(1,i-m+1,i);
            sum-=get_ans(i-m,ls);
            sum+=get_ans(i,mi);
            if(ls>mi)
                sum+=(m-1.0)*(ls-mi);
            else if(ls<mi)
                sum-=(mi-ls)*(m-1.0);
            ls=mi;
            ans=min(sum,ans);
        }
        printf("Case #%d: %.1f
",cs++,ans);
    }

    return 0;
}
原文地址:https://www.cnblogs.com/weeping/p/5734926.html