CODEVS3037 线段覆盖 5[序列DP 二分]

3037 线段覆盖 5 

时间限制: 3 s

空间限制: 256000 KB

题目等级 : 钻石 Diamond

题解

题目描述 Description

数轴上有n条线段,线段的两端都是整数坐标,坐标范围在0~10^18,每条线段有一个价值,请从n条线段中挑出若干条线段,使得这些线段两两不覆盖(端点可以重合)且线段价值之和最大。

输入描述 Input Description

第一行一个整数n,表示有多少条线段。

接下来n行每行三个整数, ai bi ci,分别代表第i条线段的左端点ai,右端点bi(保证左端点<右端点)和价值ci。

输出描述 Output Description

输出能够获得的最大价值

样例输入 Sample Input

3

1 2 1

2 3 2

1 3 4

样例输出 Sample Output

4

数据范围及提示 Data Size & Hint

n <= 1000000

0<=ai,bi<=10^18

0<=ci<=10^9

数据输出建议使用long long类型(Pascal为int64或者qword类型)



也是按r排序

一开始想f[i]表示以i为最后一个线段的最大价值

然后并不好二分

发现其实f[i]表示前i个点最大价值就可以

f[i]=max(f[i-1],f[Bin(i)]+a[i].w)

二分时还是找最靠右的符合要求的区间i,不会丢解

//
//  main.cpp
//  codevs3012
//
//  Created by Candy on 10/17/16.
//  Copyright © 2016 Candy. All rights reserved.
//

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N=1e6+5;
inline ll read(){
    char c=getchar();ll x=0,f=1;
    while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=getchar();}
    while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘;c=getchar();}
    return x*f;
}
int n;
struct seg{
    ll l,r,w;
    bool operator <(const seg &x)const{return r<x.r;}
}a[N];
ll f[N];
int Bin(int x){
    int l=1,r=x-1,m,ans=0;
    while(l<=r){
        m=(l+r)/2;
        if(a[m].r<=a[x].l) ans=m,l=m+1;
        else r=m-1;
    }
    return ans;
}
void dp(){
    for(int i=1;i<=n;i++)
        f[i]=max(f[i-1],f[Bin(i)]+a[i].w);
}
int main(int argc, const char * argv[]) {
    n=read();
    for(int i=1;i<=n;i++){
        a[i].l=read(),a[i].r=read();a[i].w=read();
        //if(a[i].l>a[i].r) swap(a[i].l,a[i].r);
    }
    sort(a+1,a+1+n);
    dp();
    printf("%lld",f[n]);
    return 0;
}
时间: 2024-08-20 14:56:55

CODEVS3037 线段覆盖 5[序列DP 二分]的相关文章

[HAOI2006] 数字序列 - dp,二分

现在我们有一个长度为n的整数序列A.但是它太不好看了,于是我们希望把它变成一个单调严格上升的序列.但是不希望改变过多的数,也不希望改变的幅度太大.求在改变的数最少的情况下,每个数改变的绝对值之和的最小值. \(n\leq 35000\),保证数据随机 Solution 第一问很容易,只需要令 \(b_i=a_i-i\),然后跑最长不下降子序列即可 下面考虑第二问,令 \(f[i]\) 表示前 \(i\) 个数构成的数列要变成单调上升需要改动的最小幅度 若 \(a_i,a_j, i<j\) 满足

【codevs】【DP】3027线段覆盖2

题目描述 Description 数轴上有n条线段,线段的两端都是整数坐标,坐标范围在0~1000000,每条线段有一个价值,请从n条线段中挑出若干条线段,使得这些线段两两不覆盖(端点可以重合)且线段价值之和最大. n<=1000 输入描述 Input Description 第一行一个整数n,表示有多少条线段. 接下来n行每行三个整数, ai bi ci,分别代表第i条线段的左端点ai,右端点bi(保证左端点<右端点)和价值ci. 输出描述 Output Description 输出能够获得

3027 线段覆盖 2

题目描述 Description 数轴上有n条线段,线段的两端都是整数坐标,坐标范围在0~1000000,每条线段有一个价值,请从n条线段中挑出若干条线段,使得这些线段两两不覆盖(端点可以重合)且线段价值之和最大. n<=1000 输入描述 Input Description 第一行一个整数n,表示有多少条线段. 接下来n行每行三个整数, ai bi ci,分别代表第i条线段的左端点ai,右端点bi(保证左端点<右端点)和价值ci. 输出描述 Output Description 输出能够获得

【BZOJ-3589】动态树 树链剖分 + 线段树 + 线段覆盖(特殊的技巧)

3589: 动态树 Time Limit: 30 Sec  Memory Limit: 1024 MBSubmit: 405  Solved: 137[Submit][Status][Discuss] Description 别忘了这是一棵动态树, 每时每刻都是动态的. 小明要求你在这棵树上维护两种事件 事件0: 这棵树长出了一些果子, 即某个子树中的每个节点都会长出K个果子. 事件1: 小明希望你求出几条树枝上的果子数. 一条树枝其实就是一个从某个节点到根的路径的一段. 每次小明会选定一些树枝

hdu 1025 Constructing Roads In JGShining&#39;s Kingdom(DP + 二分)

此博客为转发 Constructing Roads In JGShining's Kingdom Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Problem Description JGShining's kingdom consists of 2n(n is no more than 500,000) small cities which are located in t

2017级算法模拟上机准备篇(序列DP 进阶_1)

进阶版的序列DP 从一道题的优化开始 ModricWang的序列问题 题目描述:给定一个序列,求出这个序列中的最长上升子序列的长度. 这道题的本质还是求解一个最长上升子序列的问题 相对与之前提到过的O(n^2)的算法 我们可以重新整理思路 用O(nlogn)的思路来写,用贪心和二分优化之前的算法 我们设置新的DP数组//dp[i]代表的是当前长度为i的上升子序列的末尾元素的大小 状态转移方程为如果dp[len] < ar[i] 那么就将数ar[i]加到dp数组尾部. 反之,说明可以继续优化,显然

cogs265.线段覆盖

265. 线段覆盖 ★★★☆   输入文件:xdfg.in   输出文件:xdfg.out   简单对比 时间限制:2 s   内存限制:20 MB [问题描述] 有一根长度为 L 的白色条状物.有两种操作: 用一条长度为 T 的黑布盖住条状物的 [a, a+T] 这个区间 (0<=a, T<=L) . 把某条黑布拿走. 输入 L 和 n 次操作,要你输出每次操作之后: 条状物上有多少个黑区间. 条状物上黑区间的总长度. [输入格式] 输入文件第一行两个整数L(1<=L<=2000

POJ-2533最长上升子序列(DP+二分)(优化版)

Longest Ordered Subsequence Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 41944   Accepted: 18453 Description A numeric sequence of ai is ordered if a1 < a2 < ... < aN. Let the subsequence of the given numeric sequence (a1, a2, ...

【学习】序列DP

做了也有一段时间的序列DP了,发现了一些规律 如果有两个字符串,一般来说,f[i][j]表示S串到第i位,T串到第j位. 如果lenS==lenT,可能可以优化到1维. 如果只有1个序列的话,一般来说f[i]表示到第i位的状态. 有一些特殊的东西:最长回文子序列是把原串倒过来然后做一遍最长公共子序列,检查一下奇偶性×2即可. 然后呢还有最长回文子串有个manacher算法来着改天要去看看. BZOJ上的题好像只做了一道呀= =好像是带计数的数列DP呀,用容斥原理搞一下就好咯. 感觉自己还是很弱还