烽火传递

题意

在某两座城市之间有 n 个烽火台,每个烽火台发出信号都有一定的代价。为了使情报准确的传递,在任意相邻的 m 个烽火台中至少要有一个发出信号。现在需要计算总共最少需要花费多少代价,才能使敌军来袭之时,情报能在这两座城市之间准确的传递。

  • 单调队列优化
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn=1e5+10,inf=1e9+7;
    int n,t,m,f[maxn][2],v[maxn];
    int q[maxn<<1],p[maxn<<1];
    int main()
    {
      freopen("flame.in","r",stdin);
      freopen("flame.out","w",stdout);
      scanf("%d",&t);
      while(t--)
      {
          scanf("%d%d",&n,&m);
          for(int i=1;i<=n;i++)scanf("%d",&v[i]); 
          int t=0,h=1;
          for(int i=1;i<=n;i++)
          { 
              int a=0;
              if(i-p[h]>m)h++;
              if(i>m)a=v[i]+q[h];else a=v[i];
              while(t>=h&&q[t]>a)t--; 
              q[++t]=a;p[t]=i;
          }
          int ans=inf;
          if(n-p[h]>=m)h++;
          for(int i=max(h,t-m+1);i<=t;i++)
          ans=min(ans,q[i]);
          printf("%d\n",ans);
      }
      return 0;
    }
    

可以加一位n+1,直接作为ans,省去后面的ans统计

可以省去一些麻烦(比如3个小时)

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1e5+10,inf=1e9+7;
int n,t,m,f[maxn][2],v[maxn];
int q[maxn<<1],p[maxn<<1];
int main()
{
    freopen("flame.in","r",stdin);
    freopen("flame.out","w",stdout);
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)scanf("%d",&v[i]); 
        int t=0,h=1;
        for(int i=1;i<=n+1;i++)//n+1
        { 
            int a=0;
            if(i-p[h]>m)h++;
            if(i>m)a=v[i]+q[h];else a=v[i];
            while(t>=h&&q[t]>a)t--; 
            q[++t]=a;p[t]=i;
        }
        printf("%d\n",q[t]);//直接输出
    }
    return 0;
}