CF777E Hanoi Factory

DP单调栈优化

看到这道题可以很自然的想到DP

设$dp[i]$表示最后一个$ring$为$i$的最大高度

首先将$b$为第一关键字,$a$为第二关键字,升序排序元素

那么对于$i$来说,它下面的$ring$的所有能转移过来的$j$,要满足$j<i$,且$b[i]>a[j]$

所以dp转移方程为$dp[i]=max{dp[j]}+h[i](j<i,b[i]>a[j])$

但这个转移时$O(n^{2})$的

那么需要找出满足条件的最大$dp$值

发现对于$i<j<k$,且$b[j]>a[i]$,$b[k]>a[j]$

$dp[i]<dp[j]<dp[k]$,那么最后的元素就一定最优,且如果有其他不满足关系,对之后没有影响

那么可以用单调栈维护信息

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const ll MAXN=1e5+10;
ll n,dp[MAXN];
struct node
{
    ll a,b,h;
}sh[MAXN];
bool cmp(node a,node b)
{
    return (a.b>b.b || (a.b==b.b && a.a>b.a));//排序
}
int main()
{
    scanf("%lld",&n);
    for (ll i=1;i<=n;i++)
      scanf("%lld%lld%lld",&sh[i].a,&sh[i].b,&sh[i].h);
    sort(sh+1,sh+1+n,cmp);
    stack <ll> s;
    for (ll i=1;i<=n;i++)
    {
        while (!s.empty() && sh[s.top()].a>=sh[i].b)//单调栈维护信息
          s.pop();
        if (!s.empty())
          dp[i]=dp[s.top()];//转移
        dp[i]+=sh[i].h;
        s.push(i);
    }
    ll ans=0;
    for (ll i=1;i<=n;i++)
      ans=max(ans,dp[i]);
    printf("%lld
",ans);
}
原文地址:https://www.cnblogs.com/huangchenyan/p/11253218.html