Codeforces 777E/778C 题解 (贪心)

来源:互联网 发布:对淘宝客服的理解 编辑:程序博客网 时间:2024/06/06 13:25

777E Report

题意:

给出一些Hanoi tower的环的信息,分别为内径大小,外径大小和环的高度,要求这些环从下到上外径不减,且上层ring的外径必须大于下层的内径,求出可行的最大高度。


题解:

因为这道题我已经在考试后订正了,而且算法与两标程的相同,所以直接开始题解的部分。

读完题目,我的第一反应是用图还原样例,但是图示画到一半我就发现可以直接用线段来表示这些ring。对于某一个内径为ai、外径为bi的ring,在线段上被表示为一条从ai到bi的线段。那么数轴从小到大对应的就是tower上的从上到下。

考虑完模型的转化之后,考虑模型中各个ring的相互关系。由题意可知,一个ring可以承载另一个ring必须满足内径小于另一个ring的外径,且外径必须大于等于另一个ring的外径。那么这种关系表示在线段上就是:
这里写图片描述

这里要注意的就是Aj!=Bi,因为内外径相等会掉下去的。

这样就直接把问题转化到了线段上,但是目标不是获得尽可能长的线段,而是获得尽可能高的高度。换句话说,就是线段上各有一些权值,需要获得尽可能多的权值。
我们已知两个性质:

  • 如果可以选的话,选总比不选要好;
  • 我们希望,在顺次枚举线段一端的时候,另一端距离这端越远越好。因为距离越远, 就有越大的可能去再续上另一条线段。

所以说这道题贪心可做,维护一个stack表示当前选到的线段。贪心之前按照上述思路,将这些线段以bi为第一关键字,ai为第二关键字从大到小排序。然后扫一遍,如果能放进栈里就压栈,不能的话就弹到能放为止,同时维护当前高度和最高高度。


复杂度:

因为每一个ring至多进栈一次,出栈一次,所以统计答案是O(n)的,排序需要O(nlogn),所以整体的复杂度为O(nlongn)。


代码:

很短。

#include <cstdio>#include <stack>#include <algorithm>using namespace std;const int maxn=int(1e5)+10;int n;long long ans=0,cur=0;stack<int> s;struct Hanoi {    int a,b,h;    bool operator < (const Hanoi &x) const {return (b^x.b)?(b>x.b):(a>x.a);}    void read() {scanf("%d%d%d",&a,&b,&h);}}r[maxn];int main() {    scanf("%d",&n);    for(int i=0;i<n;i++) r[i].read();    sort(r,r+n);    for(int i=0;i<n;i++) {        while(s.size() && r[s.top()].a>=r[i].b) {            cur-=r[s.top()].h;            s.pop();        }        s.push(i);        cur+=r[i].h;        ans=max(ans,cur);    }    printf("%I64d\n",ans);    return 0;}
1 0
原创粉丝点击