poj1769 线段树优化的dp

  附上这道题的链接:http://poj.org/problem?id=1769

  题目的意思是有一个装置可以输出n个数的最大值, 这个装置由m个排序器组成, 每个排序器可以将这n个数从s 到 t的数按照从小到大的顺序排列, 有一个人发现将m个排序器中的一些排序器去掉仍然不影响功能,  现在问你最少需要多少个排序器可以完成功能。 我们可以定义dp[i][j]为前i个排序器将第1个数提到j所需要的最少的排序器的数量, 那么当t[i] == j的时候 dp[i][j] = min(dp[i-1][j] , min(dp[i-1][si -- ti]) + 1)  当ti != j的时候 dp[i][j] = dp[i-1][j],  我们观察状态数有m*n个, 显然直接求解会超时, 因此我们考虑使用线段树来优化  见挑战程序设计 p207 , 代码如下:

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
const int maxn = 500000 + 100;
const int inf = 0x3f3f3f3f;
int n, m;

struct segment{
    int l, r;
    int x;
}seg[3*maxn];

void build(int rt, int l, int r) {
    seg[rt].l = l; seg[rt].r = r;
    if(l == r) {
        int value = inf;
        if(l == 1) value = 0;
        seg[rt].x = value;
        return ;
    }
    int chl = 2*rt, chr = 2*rt + 1;
    int mid = (l + r) / 2;
    build(chl, l, mid);
    build(chr, mid+1, r);
    seg[rt].x = min(seg[chl].x, seg[chr].x);
}

int query(int rt, int l, int r) {
    if(seg[rt].l == l && seg[rt].r == r) {
        return seg[rt].x;
    }
    int mid = (seg[rt].l + seg[rt].r)/2;
    if(r <= mid)
        return query(2*rt, l, r);
    else if(l > mid)
        return query(2*rt+1, l, r);
    else{
        int v1 = query(2*rt, l, mid);
        int v2 = query(2*rt+1, mid+1, r);
        return min(v1, v2);
    }
}

void update(int rt, int i, int c) {
    if(seg[rt].l==seg[rt].r && seg[rt].l == i) {
        seg[rt].x = c;
        return ;
    }
    int mid = (seg[rt].l + seg[rt].r)/2;
    if(i <= mid)
        update(2*rt, i, c);
    else
        update(2*rt+1, i, c);
    seg[rt].x = min(seg[2*rt].x, seg[2*rt+1].x);
}

int main() {
    while(scanf("%d%d", &n, &m) != EOF) {
        build(1, 1, n);
        for(int i=0; i<m; i++) {
            int s, t;
            scanf("%d%d", &s, &t);
            int v1 = query(1, s, t) + 1;
            int v2 = query(1, t, t);
            int v3 = min(v1, v2);
            update(1, t, v3);
        }
        printf("%d\n", query(1, n, n));
    }
    return 0;
}
时间: 2024-11-09 00:50:49

poj1769 线段树优化的dp的相关文章

[Poi2010]Monotonicity 2 (线段树优化DP)

题目描述 给出N个正整数a[1..N],再给出K个关系符号(>.<或=)s[1..k].选出一个长度为L的子序列(不要求连续),要求这个子序列的第i项和第i+1项的的大小关系为s[(i-1)mod K+1].求出L的最大值. 输入 第一行两个正整数,分别表示N和K (N, K <= 500,000).第二行给出N个正整数,第i个正整数表示a[i] (a[i] <= 10^6).第三行给出K个空格隔开关系符号(>.<或=),第i个表示s[i]. 输出 一个正整数,表示L的

HDU4719-Oh My Holy FFF(DP线段树优化)

Oh My Holy FFF Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others) Total Submission(s): 606    Accepted Submission(s): 141 Problem Description N soldiers from the famous "*FFF* army" is standing in a line, from le

hdu 4719 Oh My Holy FFF(dp线段树优化)

Oh My Holy FFF Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others) Total Submission(s): 848    Accepted Submission(s): 219 Problem Description N soldiers from the famous "*FFF* army" is standing in a line, from le

题解 HDU 3698 Let the light guide us Dp + 线段树优化

http://acm.hdu.edu.cn/showproblem.php?pid=3698 Let the light guide us Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 62768/32768 K (Java/Others) Total Submission(s): 759    Accepted Submission(s): 253 Problem Description Plain of despair was

BZOJ 1835 基站选址(线段树优化DP)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1835 题意:有N个村庄坐落在一条直线上,第 i(i>1)个村庄距离第1个村庄的距离为Di.需要在这些村庄中建立不超过K个通讯基站,在第i个村庄建立基站的费用为Ci.如果在距离第i个村 庄不超过Si的范围内建立了一个通讯基站,那么就成它被覆盖了.如果第i个村庄没有被覆盖,则需要向他们补偿,费用为Wi.现在的问题是,选择基站的位 置,使得总费用最小. 思路: 另外,程序中的n=n+1,m=

【bzoj3939】[Usaco2015 Feb]Cow Hopscotch 动态开点线段树优化dp

题目描述 Just like humans enjoy playing the game of Hopscotch, Farmer John's cows have invented a variant of the game for themselves to play. Being played by clumsy animals weighing nearly a ton, Cow Hopscotch almost always ends in disaster, but this has

降临(线段树优化dp)

降临 选定点i会有代价\(c_i\),如果一个区间j内的点全被选择,就可以获得回报\(p_j\).点数和区间个数\(<1e5\). 还以为是线段树优化网络流(50万个点200万条边看上去很可做的样子毕竟lbn说过网络流20万万条边完全没问题),没想到是个线段树dp. (虽然这两个线段树完全扯不上关系) 用\(f[i][j]\)表示考虑到第i个点,向左最近的尚未选定的点为j时的最大值.那么,i+1可以选也可以不选.不选i时,\(f[i][j]\rightarrow f[i+1][i+1]\).选i

【CF675E】Trains and Statistic(贪心,DP,线段树优化)

题意:a[i]表示从第i个车站可以一张票到第[i+1,a[i]]这些车站;p[i][j]表示从第i个车站到第j个车站的最少的票数,现在要求∑dp[i][j](1<=i<=n,i<j<=n); 思路:从I开始走,在i+1到a[i]之间一定会到使a[j]最大的j,因为要使步数最小,接下来能走得更快 区间询问最值用RMQ与线段树都可以 dp[i]表示dp[i,i+1],dp[i,i+2]...dp[i,n]这些值的和 dp[i]=dp[k]+(n-i)-(a[i]-k),k为[i+1,a

bzoj 1835 基站选址(线段树优化Dp)

Description 题意:有N个村庄坐落在一条直线上,第i(i>1)个村庄距离第1个村庄的距离为Di 需要在这些村庄中建立不超过K个通讯基站,在第i个村庄建立基站的费用为Ci 如果在距离第i个村庄不超过Si的范围内建立了一个通讯基站,那么就成它被覆盖了 如果第i个村庄没有被覆盖,则需要向他们补偿,费用为Wi 现在的问题是,选择基站的位置,使得总费用最小. Solution 首先可以想到dp,用dp[i][j]表示前i个村庄建了j个通讯站且第j个建在i处 dp[i][j]=min(dp[k][