POJ 1769(Minimizing maximizer) 线段树优化的dp

题意:是有一个装置可以输出n个数的最大值, 这个装置由m个排序器组成, 每个排序器可以将这n个数从s 到 t的数按照从小到大的顺序排列, 有一个人发现将m个排序器中的一些排序器去掉仍然不影响功能,  现在问你最少需要多少个排序器可以完成功能。

思路:dp[i][j]表示更新到第i个区间,到第j个位置最小要几个区间。// 对线段树还是不太熟悉

T代码:

#include <queue>
#include<iostream>
#include<stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <ctime> 
#include <queue>
using namespace std;
int dp[55000];
int main(){
    int i,j,k,f1,f2,f3,f4,t1,t2,t3,t4,n,m;
//    freopen("in.txt","r",stdin);
    cin >> n>> m;
        for(i=0;i<=n;i++)
    dp[i]=1e9+7;
    dp[1]=0;  //移动到1的费用为0 
    for(i=1;i<=m;i++){
        scanf("%d %d",&t1,&t2);
        for(j=t1;j<=t2;j++){
            if(j==t1){
                f1=dp[j];
                if(f1+1>=dp[t2])break;
            }else if(j>t1&&j<=t2){
                dp[j]=min(dp[j],f1+1);
            }
    //    cout << j <<"的费用为"  << dp[j] << endl; 
        }
    }
    cout << dp[n] << endl;
    return 0;
}
View Code

AC代码:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring> // for memset
#include <vector> // push_back() // vector<int>().swap(v);
#include <set> //multiset set<int,greater<int>> //big->small
#include <map>
#include <stack> // top()
#include <queue> // front() // priority_queue<T,vector<T>,greater<T> >
#include <cmath> // auto &Name : STLName  Name.
#include <utility>
#include <sstream>
#include <string> // __builtin_popcount (ans); // 获取某个数二进制位1的个数
#include <cstdlib> // rand()

#define IOS ios_base::sync_with_stdio(0); cin.tie(0)
#define lowbit(x) (x&(-x))
using namespace std;
typedef long long ll;

const int INF = 0x3f3f3f3f;
const int maxn = 5e5 + 5;
struct T{
    int l,r,m;
}tree[maxn*4];

int ans,m,n,t1,t2;

void build(int l,int r,int num)
{
    tree[num].l=l;
    tree[num].r=r;
    if(l==r)
    {
        if(l==1)tree[num].m=0;
        else    tree[num].m=INF;
        return;
    }
    int m=(l+r)/2;
    build(l,m,num*2);
    build(m+1,r,num*2+1);
    tree[num].m=min(tree[num*2].m,tree[num*2+1].m);
}

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

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

int main(void)
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        build(1,n,1);

        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&t1,&t2);
            int v1=query(t1,t2,1)+1;
            int v2=query(t2,t2,1);
            int v3=min(v1,v2);
            update(1,t2,v3);
        }
        printf("%d\n",query(n,n,1));
    }

    return 0;
}

 

 

  

posted @ 2020-05-31 12:42  ジャスミン  阅读(140)  评论(0编辑  收藏  举报