【线段树+dp】 acdream 1074 风之国

线段树和DP的综合题,思路非常巧妙~~~acdream的比赛我一般都会做,因为时间点比较好,不想CF的时间。。。当时比赛的时候不会做(当时我还不会线段树,其实现在也没学好QAQ),看了题解以后补上。。。。题解在此ACdream题解链接。

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define maxn 100005
#define eps 1e-6
#define mod 1000000007
#define INF 99999999
#define lowbit(x) (x&(-x))
#define lson o<<1, L, mid
#define rson o<<1 | 1, mid+1, R
typedef long long LL;
using namespace std;

struct city
{
	int x, number;
}c[maxn];
int id[maxn];
int pre[maxn];
int minv[maxn<<2];
int n, m, p, v;
int ql, qr;

void init(void)
{
	memset(minv, 0, sizeof minv);
	memset(pre, -1, sizeof pre);
}
int cmp(city a, city b)
{
	return a.xb) swap(a, b);
		pre[b]=max(pre[b], a);
	}
}
void updata(int o, int L, int R)
{
	if(L==R){
		minv[o]=v;
		return;
	}
	int mid=(R+L)>>1;
	if(p<=mid) updata(lson);
	else updata(rson);
	minv[o]=min(minv[o<<1], minv[o<<1 | 1]);
}
int query(int o, int L, int R)
{
	if(ql<=L && qr>=R) return minv[o];
	int mid=(R+L)>>1, ans=INF;
	if(ql<=mid) ans=min(ans, query(lson));
	if(qr>mid) ans=min(ans, query(rson));
	return ans;
}
void solve(void)
{
	int limit=0, dp=0;
	for(int i=1;i<=n;i++){
		if(pre[i]!=-1) limit=max(pre[i], limit);
		ql=limit, qr=i-1;
		if(ql>=1 && qr>=1) dp=query(1, 1, n);
		p=i, v=dp+c[i+1].x-c[i].x;
		updata(1, 1, n);
	}
	printf("%d\n", dp);
}
int main(void)
{
	while(scanf("%d%d",&n,&m)!=EOF){
		init();
		work();
		solve();
	}
	return 0;
}


你可能感兴趣的:(线段树,DP)