zoukankan      html  css  js  c++  java
  • poj 3017 单调队列(附加multiset)

    只能说是代码美如画。(当然我是指内在逻辑不是我的代码风格,队长看到要理解哈,啊哈哈哈哈哈哈哈哈)

    正常思路咯,f[i]=f[j]+max(a[j+1],a[j+2]....a[i]),枚举j,显然硬来会超时,所以需要有一个单调队列来时时把最大值尽快弄出来并且需要一些剪枝;

    剪枝条件有两个,一个是和不能超过m,一个是显然f[i]是个非严格递增序列,根据这两个条件剪枝;

    则建立单调队列,每当插入新的i时将前面先把和小于等于m的条件做好,然后对于j<i,如果a[j]<a[i]就可以把j丢弃,那么显然新加入的元素会成为单调队列中最小的,则单调队列为递减序列。

    然后就看代码吧

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <set>
     4 #include <iostream>
     5 #include <map>
     6 #include <math.h>
     7 #include <algorithm>
     8 #include <vector>
     9 using namespace std;
    10 
    11 typedef long long ll;
    12 
    13 const int N=100005;
    14 const long long INF=1000000000ll;
    15 int n;
    16 ll m;
    17 ll a[N],f[N];
    18 ll solve(){
    19 int i,j,k=0,fg=0,l=0,r=0;
    20 int q[N];
    21 ll sum=0;
    22 for(i=1;i<=n;i++){
    23     sum+=a[i];
    24     while(sum>m) sum-=a[++k];
    25     if(k>=i){
    26         fg=1;
    27         break;
    28     }
    29    while(l<=r&&a[q[r]]<=a[i]) r--;//等于号是细节
    30    q[++r]=i;
    31    while(l<=r&&q[l]<=k) l++;
    32    ll tmp;
    33    int kk=k;
    34       f[i]=INF;
    35         //cout<<l<<" "<<r<<" "<<kk<<endl;
    36         for ( j=l; j<=r; j++) //队列优化后的dp过程,加入过程保证了单调队列中元素是递减的
    37         {
    38             tmp=f[kk]+a[q[j]];
    39           //cout<<tmp<<" "<<f[i]<<" "<<i<<" "<<kk<<endl;
    40             if (tmp<f[i]) f[i]=tmp;
    41             kk=q[j]; //kk表示当前最值存在的区间范围是[kk+1,i]
    42         }
    43 //f[i]=tmp;
    44 //cout<<f[i]<<" "<<i<<endl;
    45 }
    46 if(fg)
    47     return -1;
    48 else
    49     return f[n];
    50 }
    51 int main()
    52 {
    53    freopen("in.txt","r",stdin);
    54    cin>>n>>m;
    55    int i;
    56    for(i=1;i<=n;i++)
    57     scanf("%lld",&a[i]);
    58   cout<<solve()<<endl;
    59     return 0;
    60 }

     再加一种用multiset的

    #include <cstdio>
    #include <cstring>
    #include <set>
    #include <iostream>
    #include <map>
    #include <math.h>
    #include <algorithm>
    #include <vector>
    using namespace std;
    
    typedef long long ll;
    
    const int N=100005;
    const long long INF=1000000000ll;
    int n;
    ll m;
    ll a[N],f[N];
    multiset<int>q1;
    ll solve(){
    int i,j,k=0,fg=0,l=0,r=-1;//为了初始化所以r=-1,引发一系列麻烦事
    int q[N];
    ll sum=0;
    for(i=1;i<=n;i++){
        sum+=a[i];
        while(sum>m) sum-=a[++k];
        if(k>=i){
            fg=1;
            break;
        }
       while(l<=r&&a[q[r]]<=a[i]){if(l<r) q1.erase(f[q[r-1]]+a[q[r]]);r--;}//等于号是细节
       q[++r]=i;
      if(l<r) q1.insert(f[q[r-1]]+a[i]);
       while(l<=r&&q[l]<=k) {if(l<r) q1.erase(f[q[l]]+a[q[l+1]]);l++;}
       ll tmp=*(q1.begin());
       f[i]=f[k]+a[q[l]];
       if(tmp<f[i]&&l<r) f[i]=tmp;
    
    //f[i]=tmp;
    //cout<<f[i]<<" "<<i<<endl;
    }
    if(fg)
        return -1;
    else
        return f[n];
    }
    int main()
    {
       freopen("in.txt","r",stdin);
       cin>>n>>m;
       int i;
       for(i=1;i<=n;i++)
        scanf("%lld",&a[i]);
      cout<<solve()<<endl;
        return 0;
    }
  • 相关阅读:
    Chevy equinox
    回家线路
    salesforce account hierarchy
    IOS8 对flex兼容性问题
    Chrome FeHelper 插件下载地址
    vue 项目抛出警告
    vue 干货
    Error in mounted hook: "TypeError: handlers[i].call is not a function" 原因
    vue 路由知识点(一级路由与二级路由嵌套)
    (转)ORA-01940: cannot drop a user that is currently connected 问题解析
  • 原文地址:https://www.cnblogs.com/shimu/p/5656486.html
Copyright © 2011-2022 走看看