poj1769(Minimizing maximizer)dp+线段树

 

Description

The company Chris Ltd. is preparing a new sorting hardware called Maximizer. Maximizer has n inputs numbered from 1 to n. Each input represents one integer. Maximizer has one output which represents the maximum value present on Maximizer's inputs. 

Maximizer is implemented as a pipeline of sorters Sorter(i1, j1), ... , Sorter(ik, jk). Each sorter has n inputs and n outputs. Sorter(i, j) sorts values on inputs i, i+1,... , j in non-decreasing order and lets the other inputs pass through unchanged. The n-th output of the last sorter is the output of the Maximizer. 

An intern (a former ACM contestant) observed that some sorters could be excluded from the pipeline and Maximizer would still produce the correct result. What is the length of the shortest subsequence of the given sequence of sorters in the pipeline still producing correct results for all possible combinations of input values? 

Task 
Write a program that: 

reads a description of a Maximizer, i.e. the initial sequence of sorters in the pipeline, 
computes the length of the shortest subsequence of the initial sequence of sorters still producing correct results for all possible input data, 
writes the result. 

Input

The first line of the input contains two integers n and m (2 <= n <= 50000, 1 <= m <= 500000) separated by a single space. Integer n is the number of inputs and integer m is the number of sorters in the pipeline. The initial sequence of sorters is described in the next m lines. The k-th of these lines contains the parameters of the k-th sorter: two integers ik and jk (1 <= ik < jk <= n) separated by a single space.

Output

The output consists of only one line containing an integer equal to the length of the shortest subsequence of the initial sequence of sorters still producing correct results for all possible data.

Sample Input

40 6
20 30
1 10
10 20
20 30
15 25
30 40

Sample Output

4

 

 

 

 

题意:从m个区间中选取最少的区间覆盖[1, n],覆盖顺序和给定的顺序相同。

 

题解:如果没有后半句话,那么这题很简单,排序然后贪心选取就行。现在给定了顺序,就不能这么做了。

用动态规划,设第i个区间为[si, ti],dp[i][j]表示处理到第i个区间且覆盖区间最右端为j需要的最少区间数。

ti != j时,dp[i][j] = dp[i-1][j];ti = j时,dp[i][j] = min(dp[i-1][j], min{dp[i-1][j'] | si <= j' <= ti} + 1)。

这样复杂度为O(mn),太高,想其他办法吧。由于i是有i-1得到的,所以可以减少一维。对于每一个i,

dp[ti] = min(dp[ti], min{dp[j'] | si <= j' <= ti} + 1)

貌似这样复杂度降到了O(m),但是最坏情况下仍然可能达到O(mn),这时可以使用线段树来维护区间最小值,这样复杂度就降到了O(mlogn)

第一次独立写线段树,以前都是抄模板的。。。

 

 

#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <map>
#include <vector>
#include <list>
#include <set>
#include <stack>
#include <queue>
#include <deque>
#include <algorithm>
#include <functional>
#include <numeric>
#include <iomanip>
#include <limits>
#include <new>
#include <utility>
#include <iterator>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <cmath>
#include <ctime>
using namespace std;

const int INF = 0x3f3f3f3f;
const int maxn = 50010;

int dp[maxn];
int st[1<<18];
int n, m;

void build(int k, int l, int r)
{
    st[k] = INF;
    if (r - l == 1)
        return;
    build(k*2+1, l, (l+r)>>1);
    build(k*2+2, (l+r)>>1, r);
}

void update(int s, int x, int k, int l, int r)
{
    if (r - l > 1)
    {
        int m = (l + r) >> 1;
        if (s < m)
            update(s, x, k*2+1, l, m);
        else
            update(s, x, k*2+2, m, r);
    }
    st[k] = min(st[k], x);
}

int query(int a, int b, int k, int l, int r)
{
    if (a <= l && b >= r)
        return st[k];
    if (b <= l || a >= r)
        return INF;
    int vl = query(a, b, k*2+1, l, (l+r)>>1);
    int vr = query(a, b, k*2+2, (l+r)>>1, r);
    return min(vl, vr);
}

int main()
{
    cin >> n >> m;
    build(0, 0, n);
    fill(dp, dp+n, INF);
    dp[0] = 0;
    update(0, 0, 0, 0, n);
    while (m--)
    {
        int s, t;
        scanf("%d%d", &s, &t);
        int v = min(dp[t-1], query(s-1, t, 0, 0, n)+1);
        dp[t-1] = v;
        update(t-1, v, 0, 0, n);
    }
    printf("%d\n", dp[n-1]);
    return 0;
}

 

 

 

 

 

 

算法码上来 文章被收录于专栏

公众号「算法码上来」。godweiyang带你学习算法,不管是编程算法,还是深度学习、自然语言处理算法都一网打尽,更有各种计算机新鲜知识和你分享。别急,算法码上来。

全部评论

相关推荐

其实本来打算等lastday的时候再写的,但是现在提笔写下这篇总结完全是出于自己的想法,今天上午自己被学校发的签到吵醒时才突然想明白了很多事情,遂决定写下本文进行总结,虽然现在顶多算2.5个月,但也大差不差喵。回看这段时间的日常实习,我的关键词是:遗憾,焦虑。当然也有快乐的时候,不过大部分时间都是前面这两种情绪主导。为了避免后人再次踩坑,我将在本文详细解释我遇到的困难&nbsp;+&nbsp;产生的原因&nbsp;+&nbsp;应对的措施。同时总结新人实习时除了业务本身,还有如何处理生活与工作上的平衡,调控自身的情绪,让自己恢复到最好的工作状态。本文不会教你实习怎么去做产出,因为有产出的前提是你的心态足够健康,且在工作之余还有时间去...
wuwuwuoow:你的经历跟挺像,但我实力远没你强,现在只能干外包。但解决焦虑这块我应该比你更有经验,因为我曾经也非常迷茫和焦虑: 1.规律作息。无论节假日,都必须在同一时间点睡觉,同一时间点起床。放假睡的多,工作睡的少,这就是典型的作息不规律。将直接干扰前额叶皮层功能,导致情绪波动(易怒、焦虑)。无论上班还是周末,我都是 11:30 睡,7 点起床。7.5h 睡眠,完全足够了。 2.运动。缓解压力,强身健体,提高免疫力。不要觉得每天没有时间锻炼,都是懒惰的借口。 3.冥想。长期练习会增厚前额叶皮层(理性决策区),缩小杏仁核体积(减少情绪过敏反应,核心),增强情绪调控能力。 方法很简单,任何时候都能做。就是闭上眼睛,只专注自己的呼吸,不去想其他任何事情。你可以尝试一下,你会发现非常难只专注呼吸,会有大量的想法涌现出来(什么走马灯),不要去压抑它们,而是放平心态,把注意力继续放在呼吸上面。 而且最重要的是,冥想让你学会“活在当下”。因为处于冥想的你,除了专注呼吸你还能做什么呢?你什么都做不了。生活也是这样,我们无法改变过去,无法预知未来会发生什么,我们能做的只有手头的事情,除此之外什么都别想,因为你无法去改变它们。 4.工作与生活分离。工作不是生活的全部,生活可不是只有工作。像我放假的时候,从不带电脑回去。放假该玩就玩吧。 上面要是都能做到,其实完全解决不了你工作上的问题,完不成的需求还是完不成,面试该挂还是得挂。不过呢,当你再次迷茫,再次焦虑的时候,你会发现,诶,还好,没这么难受。比如面试挂了,可能以前的你会感觉非常难受。但如果你做到以上 4 点,你还是会难受的,但其实又没这么难受,可能你会这样想:既然挂了我还能怎么样?这公司不要我,有的是公司要我!
投递腾讯等公司10个岗位 >
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务