POJ 1769(DP,线段树

虽然是基本的dp和线段树,但是线段树依然写错了好几处,查错也查了好久,其实只要写的时候画个示意图,把下标写对就好了

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<utility>
#include<vector>
#include<cstring>
#include<cmath>
#define INF 0x7fffffff
#define pb push_back
#define pn(x) cerr<<x<<endl

using namespace std;
typedef long long ll;
const int maxv=500005;
int n,m;
int l[maxv],r[maxv];
int dat[50000*4];
int _n;
int query(int k,int a,int b,int l,int r){
    if(a>=r||b<=l) return INF;
    if(a<=l&&b>=r) return dat[k];///此处一开始漏写了。。
    int chl=k*2+1,chr=k*2+2,m=(l+r)/2;
    return min(query(chl,a,b,l,m),query(chr,a,b,m,r));
}
void update(int k,int a){
    k+=_n/2-1;////此处写成了+=_n/2.................
    dat[k]=a;
    while(k>0){
        k=(k-1)>>1;/////此处写成了k>>=1.............
        int chl=k*2+1,chr=k*2+2;
        dat[k]=min(dat[chr],dat[chl]);
    }
    return;
}
int dp[50005];////表示前i个s覆盖达到j时最小个数
int main(){
    freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    cin>>n>>m;
    for(int i=0;i<m;i++) scanf("%d%d",&l[i],&r[i]);
    memset(dp,0x3f,sizeof dp);
    memset(dat,0x3f,sizeof dat);
    _n=1;
    while(_n<n*2) _n<<=1;
    dp[0]=0;
    update(0,0);
    int IN=dp[2];
    for(int i=0;i<m;i++){
        int tt=query(0,l[i]-1,r[i],0,_n/2);////下标比较混乱,实际上线段树统一写成左闭右开区间,下标从0开始就好,这样思路比较清晰,不容易出错
        if(tt+1<dp[r[i]-1]){
            update(r[i]-1,tt+1);
            dp[r[i]-1]=tt+1;
        }
    }
    printf("%d\n",dp[n-1]);
    return 0;
}

 

posted @ 2015-05-09 13:51  PlusSeven  阅读(150)  评论(0)    收藏  举报