[2021.8集训Day2/JZOJ.1254]清理牛棚

时间:2021-08-11
本文章向大家介绍[2021.8集训Day2/JZOJ.1254]清理牛棚 ,主要包括[2021.8集训Day2/JZOJ.1254]清理牛棚 使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

[2021.8集训Day2/JZOJ.1254]清理牛棚

题目

思路

当每一个\(S\)都比较大时,总费用可能超过\(\inf\),但是数据较水,这个问题可以自行解决.

线段树优化DP

T4竟是最水的一道题?!

\(f_i\)表示前\(i\)秒都有奶牛打扫的最小代价.显然,对于每一头奶牛,有

\[f_{t_2}=\min(f_{t_2},s+\min^{t_2-1}_{i=t_1-1}f_i) \]

对于后面的取最小值,明显可以线段树优化.

把每一头奶牛按\(t_2\)​递增排序再枚举即可.

代码

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>

using namespace std;

const int N = 10010 , M = 90000;
const int INF = 0x3fffffff;

int read() {
	int re = 0;
	char c = getchar();
	bool negt = false;
	while(c < '0' || c > '9')
		negt |= (c == '-') , c = getchar();
	while(c >= '0' && c <= '9')
		re = (re << 1) + (re << 3) + c - '0' , c = getchar();
	return negt ? -re : re;
}
class SegmentTreee {
	private :
		struct TreeNode {
			int l , r , ls , rs , dat;
		}node[M * 4];
		int cnt;
	public :
		inline int newnode () {
			return ++cnt;
		}
		int build(int l , int r) {
			int id = newnode();
			node[id].l = l , node[id].r = r , node[id].dat = INF;
			if(l == r)
				return id;
			int mid = (l + r) / 2;
			node[id].ls = build(l , mid);
			node[id].rs = build(mid + 1 , r);
			return id;
		}
		void change(int p , int pos , int dat) {
			if(node[p].l == node[p].r) {
				node[p].dat = dat;
				return;
			}
				
			if(pos <= node[node[p].ls].r)
				change(node[p].ls , pos , dat);
			else
				change(node[p].rs , pos , dat);
			node[p].dat = min(node[node[p].ls].dat , node[node[p].rs].dat);
		}
		int query(int p , int l , int r) {
			if(l <= node[p].l && r >= node[p].r)
				return node[p].dat;
			if(l > node[p].r || r < node[p].l)
				return INF;
			return min(query(node[p].ls , l , r) , query(node[p].rs , l , r));
		}
}segT;
struct COW {
	int st , end , cos;
}cow[N];
bool cmp(COW a , COW b) {
	return a.end < b.end;
}

int n , m;
int root;

int cos[M];
int main() {
	n = read();
	int st = read() , end = read() , delta = st - 1;//需要打扫的时间:[1,m]
	m = end - delta;
	for(int i = 1 ; i <= n ; i++)
		cow[i].st = read() - delta , cow[i].end = read() - delta , cow[i].cos = read();
		
	sort(cow + 1 , cow + n + 1 , cmp);
	
	root = segT.build(0 , m);
	
	segT.change(root , 0 , 0);
	
	memset(cos , 0x3f , sizeof(cos));
	for(int i = 1 ; i <= n ; i++) {
		int tmp = cow[i].cos + segT.query(root , cow[i].st - 1 , cow[i].end - 1);
		if(tmp < cos[cow[i].end]) {
			cos[cow[i].end] = tmp;
			segT.change(root , cow[i].end , tmp);
		}
	}
	cout << (cos[m] == 1061109567 ? -1 : cos[m]);
	return 0;
}

最短路

(这里的边都是有向边)可以考虑建模,每一头奶牛\(t_1,t_2,s\)​从\(t_1-1\)​到\(t_2\)​连一条边权为\(s\)​的边,对于\(E-1\)​到\(M-1\)​的每一秒\(i\),​从\(i+1\)​到\(i\)​连一条边权为\(0\)​的边.从\(E-1\)​出发,\(M\)​结束,查询最短路即可

代码

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>

using namespace std;

const int N = 10010 , M = 90000;
const int INF = 0x3fffffff;

int read() {
	int re = 0;
	char c = getchar();
	bool negt = false;
	while(c < '0' || c > '9')
		negt |= (c == '-') , c = getchar();
	while(c >= '0' && c <= '9')
		re = (re << 1) + (re << 3) + c - '0' , c = getchar();
	return negt ? -re : re;
}
struct EDGE {
	int to , nxt , val;
}ed[M + N];
int head[M];
void addedge(int u , int v , int val) {
	static int cnt = 0;
	++cnt;
	ed[cnt].to = v , ed[cnt].val = val , ed[cnt].nxt = head[u] , head[u] = cnt;
}

int n , m;

bool inq[M];
int dis[M];
void spfa() {//懒得写dij,勿喷SPFA QAQ
	memset(dis , 0x3f , sizeof(dis));
	dis[0] = 0;
	
	queue <int> q;
	inq[0] = true , q.push(0);
	while(!q.empty()) {
		int u = q.front();
		inq[u] = false , q.pop();
		for(int i = head[u] ; i ; i = ed[i].nxt) {
			int v = ed[i].to;
			if(dis[v] > dis[u] + ed[i].val) {
				dis[v] = dis[u] + ed[i].val;
				if(!inq[v])
					inq[v] = true , q.push(v);
			}
		}
	}
} 
int main() {
	n = read();
	int st = read() , end = read() , delta = st - 1;
	m = end - delta;
	
	for(int i = 0 ; i < m ; i++)
		addedge(i + 1  , i , 0);
	for(int i = 1 ; i <= n ; i++) {
		int u = read() - delta - 1 , v = read() - delta , val = read();
		addedge(u , v , val);
	}
	
	spfa();
	cout <<  (dis[m] == 1061109567 ? -1 : dis[m]);
	return 0;
}

原文地址:https://www.cnblogs.com/dream1024/p/15127051.html