首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >种树 差分约束|贪心

种树 差分约束|贪心

作者头像
用户2965768
发布2019-04-18 15:29:13
发布2019-04-18 15:29:13
3960
举报
文章被收录于专栏:wymwym

 先看贪心版本。

每次种的树在重叠区间越多,种的树越少。只有结束位置才会重合,就对区间结束的位置从小到大排序。

然后遍历每个区间统计第i个区间种了k个树,若k大于 t ,则continue, 否则从区间末尾往前种树。 

代码语言:javascript
复制
//贪心种树 
#include <bits/stdc++.h>
using namespace std;
struct N{
	int s,t,e;
	bool operator < (const N b)const {
		return e<b.e;
	}
};
N node[30005];
int book[30005];
int n,m;
int main()
{
	scanf("%d",&n);
	scanf("%d",&m);
	for(int i=0;i<m;i++){
		scanf("%d %d %d",&node[i].s,&node[i].e,&node[i].t);
	}
	sort(node,node+m);
	int ans=0;
	for(int i =0;i<m;i++){
		int k = 0;
		for(int j = node[i].s;j<=node[i].e;j++)if(book[j])k++;
		if(k>=node[i].t)continue;
		for(int j=node[i].e;j>=node[i].s;j--){
			if(!book[j]){
				book[j]=1;
				k++; ans++;
				if(k>=node[i].t)break;
			}
		}
	}
	printf("%d\n",ans);
	return 0;
 } 

差分约束

题目中有这么几个约束条件

sum[i]是 i 的前缀和。

从u到v: sum[u-1] - sum[v] <= - t

从i-1到i:   sum[i] - sum[i-1] <=1  

从i到i-1:   sum[i-1] - sum[ i ]<=0

最后找一个源点也即N+1,N+1到每个点距离为0   sum[i] - sum[N+1]=0

代码语言:javascript
复制
//差分种树 
#include <bits/stdc++.h>
using namespace std;
#define INF 0x7fffffff
#define R register
struct N{
	int v,nxt,w;
};
int cnt,n,m;
int S;
N edge[100005];
int head[100005],dis[30005],book[30005];
int read(){
	int x=0,dign=1;
	char c = getchar();
	while(c<'0'||c>'9'){
		if(c=='-')dign=-1;
		c = getchar();
	}
	while(c>='0'&&c<='9'){
		x = x*10 + c - '0';
		c = getchar();
	}
	return x*dign;
}
void add(int u,int v,int w){
	cnt++;
	edge[cnt].v = v;
	edge[cnt].w = w;
	edge[cnt].nxt = head[u];
	head[u] = cnt;
}
void spfa(){
	queue<int> q;
	for(R int i=0;i<=n+1;i++)dis[i] = INF;
	dis[S] = 0; book[S] = 1; q.push(S);
	while(!q.empty()){
		int u = q.front(); book[u] = 0; q.pop();
		for(R int v,w,i = head[u];i;i=edge[i].nxt){
			v = edge[i].v; w = dis[u] + edge[i].w;
			if(dis[v]>w){
				dis[v] = w;
				if(!book[v]){
					book[v]=1; q.push(v);
				}
			} 
		}
	}
}
int main()
{
	n = read();
	m = read();
	for(R int i=0;i<m;i++){
		int u,v,w;
		u = read(); v = read(); w = read();
		add(v,u-1,-w);
	}
	for(R int i=1;i<=n;i++){
		add(i,i-1,0);
		add(i-1,i,1);
	}
	for(R int i=0;i<=n;i++)add(n+1,i,0);
	
	S = n+1;
	
	spfa();
	int mi = INF;
	for(int i=0;i<=n;i++)mi = min(mi,dis[i]);
	printf("%d\n",dis[n]-mi);
	return 0;
 } 
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019年04月08日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档