要用线段树的dp
题目描述:
一堆m~5e5可已到达[l,r]的东西,不能改变顺序的从中挑选一些,使得1个在1的东西能够交换到n~5e4.
题解:
首先是dp[i][j],考虑完i个机器,1能够移动到j所花费的最小的长度.然后看每个机器怎么去更新,对于i:l,r, 首先拿出来dp[i-1][l]的值,一定是l到r最小的,然后用i,拿这个值去修改一下dp[i][l][r]的最小值,[i]可省略,用线段树来成端更新.
一个更好的思路:考虑每一个及其的更新作用.其实lr机器的作用是,将l到r的东西能够到r,这是它基本的功能.然后从l到r中选出最小的到r,就是可能因为它才能提供的能够到r的最好值.更新的思维很重要.(考虑最后一个机器就行了).
重点:
获取状态可以用最小来描述,然而更新如果对一段区间都有影响的话,那么就必须用线段树了.
另解:考虑每个机器的作用,到r就是r,r之前的不管.但是获取l到r要遍历一遍取最值.
代码:
还有一道题目很好.
poj3171
牛来清理牧场,牛有区间覆盖牧场,并且牛无顺序,排序和线段数。
其实就是区间覆盖最小代价.
题解:dp[i]是覆盖到i的代价.然后看每一个区间的更新,ab,花费s,则从a和b中一个最小的,更新到b.然后为了没有后效性,先把牛按照b来排个序.
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <ctype.h>
#include <limits.h>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#include <stack>
#include <set>
#include <bitset>
#define CLR(a) memset(a, 0, sizeof(a))
#define REP(i, a, b) for(ll i = a;i < b;i++)
#define REP_D(i, a, b) for(ll i = a;i <= b;i++)
typedef long long ll;
using namespace std;
const ll maxn = 1e6 + 100;
const ll M_N = 1e6 + 0.1;
const ll INF = 10000000000000000L;
struct info
{
ll t1, t2, s;
};
info niu[maxn];
ll a[maxn];
ll n, m, e;
void push_up(ll rt)//线段树快速查询
{
a[rt] = min(a[rt*2], a[rt*2 + 1]);
}
void update(ll q, ll key, ll l, ll r, ll rt)
{
if(l == r)
{
a[rt] = key;
return;
}
ll m = (l +r)/2;
if(q <= m)
{
update(q, key, l, m, rt*2);
}
else
{
update(q, key, m + 1, r, rt*2 + 1);
}
push_up(rt);
}
ll query(ll L, ll R, ll l, ll r, ll rt)
{
if(L <= l && R >= r)
{
return a[rt];
}
ll ans = INF;
ll m = (l + r)/2;
if(L <= m)
{
//printf("--%d\n", rt);
ans = min(ans, query(L, R, l, m, rt*2));
}
if(R >= m + 1)
{
ans = min(ans, query(L, R, m + 1, r, rt*2 +1));
}
return ans;
}
bool cmp(info a, info b)
{
if(a.t2 == b.t2)
{
return a.t1 < b.t1;
}
return a.t2 < b.t2;
}
void solve()
{
sort(niu, niu + n, cmp);/先排序,基础
REP_D(i, 0, M_N)
{
a[i] = INF;
}
REP(i, 0, n)
{
ll temp = query(niu[i].t2, niu[i].t2, 1, e, 1);//这个写的还很嫩啊.其实不用这个temp
if(niu[i].t1 == m)//初始化把dp[m]=0,就不需要这个了
{
temp = min(temp, niu[i].s);
//temp = min(temp, query(niu[i].))
}
else
{
temp = min(temp, query(niu[i].t1 - 1, niu[i].t2 - 1, 1, e, 1) + niu[i].s);
}
update(niu[i].t2, temp, 1, e, 1);
}
ll ans = query(e, e, 1, e, 1);
if(ans != INF)
printf("%lld\n", ans);
else
printf("-1\n");
}
int main()
{
//freopen("4Din.txt", "r", stdin);
//freopen("4Dout.txt", "w", stdout);
while(scanf("%lld%lld%lld", &n, &m, &e) != EOF)
{
m++;
e++;
REP(i, 0, n)
{
scanf("%lld%lld%lld", &niu[i].t1, &niu[i].t2, &niu[i].s);
niu[i].t1++;
niu[i].t2++;
}
solve();
}
return 0;
}