UVA - 1322 Minimizing Maximizer 线段树

问题

分析

dp[i]代表覆盖了[1,i]区间的最小代价
状态 d p [ r i g h t ] = m i n i ( d p [ i ] ) + 1 , l e f t < = i < r i g h t dp[right]=min_i(dp[i])+1,left<=i<right
线段树,单点更新,区间查询

#include<iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <set>
using namespace std;
const int maxn=50000+5,INF=0x3f3f3f3f;
//使用线段树,单点更新,求区间最小值
struct Tree{
    int left,right,minv;
    Tree(int left=0,int right=0,int minv=0):left(left),right(right),minv(minv){}
}tree[maxn*4];
int dp[maxn],kase,n,m,l,r;

void pushup(int rt){
    tree[rt].minv=min(tree[rt<<1].minv,tree[rt<<1|1].minv);
}
//建树
void build(int rt,int left,int right){
    tree[rt].left=left,tree[rt].right=right;
    if(left==right){
        tree[rt].minv=INF;
        return;
    }
    int mid=(left+right)>>1;
    build(rt<<1,left,mid);
    build(rt<<1|1,mid+1,right);
    pushup(rt);
}

//更新一个点pos的值v,[left,right]=[tree[rt].left,tree[rt].right]
void update(int rt,int left,int right,int pos,int v){
    if(left==right){
        tree[rt].minv=v;
        return;
    }
    int mid=(left+right)>>1;
    if(pos<=mid) update(rt<<1,left,mid,pos,v);
    else update(rt<<1|1,mid+1,right,pos,v);
    pushup(rt); //别忘了向上更新
}

int query(int rt,int left,int right,int LEFT,int RIGHT){
    if(LEFT<=left && RIGHT>=right){  //如果这个区间被完全包围
        return tree[rt].minv;
    }
    int mid=(left+right)>>1,t1=INF,t2=INF;
    if(LEFT<=mid) t1=query(rt<<1,left,mid,LEFT,RIGHT);
    if(RIGHT>mid) t2=query(rt<<1|1,mid+1,right,LEFT,RIGHT);
    return min(t1,t2);
}

int main(void){
    cin>>kase;
    while(kase--){
        scanf("%d%d",&n,&m);
        memset(dp,INF,sizeof(dp));
        build(1,1,n);
        dp[1]=0;
        update(1,1,n,1,0);
        for(int i=0;i<m;++i){
            scanf("%d%d",&l,&r);
            int t=query(1,1,n,l,r); //查询[l,r]中的最小值
            if(t+1<dp[r]){
                dp[r]=t+1;   //更新
                update(1,1,n,r,t+1);  //更新dp[r]
            }
        }
        printf("%d\n",dp[n]);
        if(kase) printf("\n");
    }
    return 0;
}

发布了50 篇原创文章 · 获赞 0 · 访问量 688

猜你喜欢

转载自blog.csdn.net/zpf1998/article/details/104177110
今日推荐