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; }

浙公网安备 33010602011771号