POJ1201 Intervals

Intervals

给定n个区间,[ai,bi]这个区间至少选选出ci个整数,求一个集合z,满足每个区间的要求,输出集合z的大小。

题解

令d[i]表示0到i这个区间内至少要选出d[i]个数,那么对于每个[ai,bi],有d[b] - d[ai-1] >= ci,同时隐含的一个条件是0 <= d[i] - d[i-1] <= 1,但是因此d[-1]不能表示,令d[i+1]示0到i这个区间内至少要选出d[i+1]个数,然后d[0] = 0,直接求取最长路就行了。边的存储使用链式向前星,这样效率最高。

因为这不可能是网格图,时间复杂度\(O(k*3n)\)

co int N=5e4+3,M=5e5;
int n,m,d[N];
int Head[N],Edge[M],Leng[M],Next[M],tot;
bool v[N];

il void add(int x,int y,int z){
	Edge[++tot]=y,Leng[tot]=z,Next[tot]=Head[x],Head[x]=tot;
}
int main(){
	read(n),tot=m=0;
	for(int i=1,x,y,z;i<=n;++i){
		read(x),read(y),read(z);
		add(x,y+1,z),m=max(m,y+1);
	}
	for(int i=1;i<=m;++i)
		add(i-1,i,0),add(i,i-1,-1);
	memset(d,0xcf,sizeof d),d[0]=0;
	queue<int> q;
	q.push(0),v[0]=1;
	for(int x;q.size();){
		x=q.front(),q.pop(),v[x]=0;
		for(int i=Head[x],y;i;i=Next[i])
			if(d[y=Edge[i]]<d[x]+Leng[i]){
				d[y]=d[x]+Leng[i];
				if(!v[y]) q.push(y),v[y]=1;
			}
	}
	printf("%d\n",d[m]);
	return 0;
}

另外这题有个显而易见的贪心:这题把数据按b的大小进行从小到大排序。然后每次取最右边的数据,用树状数组维护即可

posted on 2019-05-29 16:19  autoint  阅读(114)  评论(0)    收藏  举报

导航