zoukankan      html  css  js  c++  java
  • tzoj 3847 Mowing the Lawn (单调队列 )

    烽火传递:https://blog.csdn.net/magical_qting/article/details/47205093

    这篇博客的题和我要写的题思路类似(我把他代码改了下 更好懂

    Description
    烽火台又称烽燧,是重要的军事防御设施,一般建在险要或交通要道上。一旦有敌情发生,白天燃烧柴草,通过浓烟表达信息;夜晚燃烧干柴,以火光传递军情,在某两座城市之间有n个烽火台,每个烽火台发出信号都有一定代价。为了使情报准确地传递,在连续m个烽火台中至少要有一个发出信号。请计算总共最少花费多少代价,才能使敌军来袭之时,情报能在这两座城市之间准确传递。

    Input
    第一行:两个整数N,M。其中N表示烽火台的个数,M表示在连续m个烽火台中至少要有一个发出信号。接下来N行,每行一个数Wi,表示第i个烽火台发出信号所需代价。

    Sample Input
    5 3
    1
    2
    5
    6
    2
    Sample Output
    4
    思路:
    dp加单调队列优化。
    f[i]表示当第i个烽火台发出信号,前i个烽火台最少付出的代价。
    f[i]=min{f[k]}(i-m<=k<=i-1)+w[i]
    单调队列维护一单调递增区间,每次队首取出最小值。

    #include<bits/stdc++.h>
    #define N 100010
    #define ll long long
    using namespace std;
    ll n,m,dp[N],que[N];
    int main()
    {
        scanf("%I64d%I64d",&n,&m);//20 3
        ll head=1,tail=0,sum=0;//head=1,tail=0
        que[++tail]=0;
        for(ll i=1;i<=n;i++)
        {
            ll w;
            scanf("%I64d",&w);
            while(que[head]<i-m)//超m的出队 
                head++;
            dp[i]=w+dp[que[head]];//更新 
            while(head<=tail&&dp[que[tail]]>=dp[i])//比较 出队 
                tail--;
            que[++tail]=i; //入队 
        }
        ll minn=1e15;
        for(ll i=n;i>n-m;i--) //20-17
            minn=min(minn,dp[i]);
        printf("%I64d
    ",minn);
        return 0;
    }
    View Code

    然后是3847:

    题意:可以获得的最大总奶牛效率,而不会选择超过m个连续奶牛

    即在m+1中选择一个地方设断点,断点的地方不选 其他选上,求选上的奶牛效率总和最大。

    而烽火那题就是在m中选一个断点(要最小),断点选上,其他不选,求选上的断点的min

    3847求得就是所有总和 减去烽火那题要求的min

    #include<bits/stdc++.h>
    #define N 100010
    #define ll long long
    using namespace std;
    ll n,m,dp[N],que[N];
    int main()
    {
        scanf("%I64d%I64d",&n,&m);//20 3
        m=m+1;//m+1中必有一个断点 
        ll head=1,tail=0,sum=0;//head=1,tail=0
        que[++tail]=0;
        for(ll i=1;i<=n;i++)
        {
            ll w;
            scanf("%I64d",&w);
            sum+=w;
            while(que[head]<i-m)//超m的出队 
                head++;
            dp[i]=w+dp[que[head]];//更新 
            while(head<=tail&&dp[que[tail]]>=dp[i])//比较 出队 
                tail--;
            que[++tail]=i; //入队 
        }
        ll minn=1e15;
        for(ll i=n;i>n-m;i--) //20-17
            minn=min(minn,dp[i]);
        printf("%I64d
    ",sum-minn);
       // for(ll i=1;i<=n;i++)cout<<dp[i]<<endl;
        return 0;
    }
    View Code
  • 相关阅读:
    Bank4
    Bank3
    Bank2
    Bank1
    Kubernetes核心技术Service
    kubernetes的Pod
    kubernetes如何快速编写yaml文件
    Kuberbetes的Secret
    Kuberbetes的Job和CronJob
    Kuberbetes的DaemonSet
  • 原文地址:https://www.cnblogs.com/ydw--/p/11190500.html
Copyright © 2011-2022 走看看