首页 > 代码库 > ZOJ3632 线段树+DP

ZOJ3632 线段树+DP

买西瓜吃,每个西瓜有两个参数,一个是p代表价格,一个是t代表能吃几天,要求n天每天都能吃西瓜,而且如果你今天买了,以前买的还没吃完 那么都得扔了,求最小花费,还真想不到用线段树+DP,最后看了一下别人的标题,想了一下,DP方程挺好推的,线段树也只是单点查询,


#include<iostream>
#include<cstdio>
#include<list>
#include<algorithm>
#include<cstring>
#include<string>
//#include<queue>
#include<stack>
#include<map>
#include<vector>
#include<cmath>
#include<memory.h>
#include<set>

#define ll long long

#define eps 1e-8

#define inf 0xfffffff

const ll INF = 1ll<<61;

using namespace std;

//vector<pair<int,int> > G;
//typedef pair<int,int > P;
//vector<pair<int,int> > ::iterator iter;
//
//map<ll,int >mp;
//map<ll,int >::iterator p;


const int N = 50005   + 5;

typedef struct Node {
	int l,r;
	int mark;//biaoji
	ll pri;
};

Node tree[N << 2];

ll p[N],t[N];

void build(int l,int r,int id) {
	tree[id].l = l;
	tree[id].r = r;
	tree[id].mark = 0;
	tree[id].pri = INF;
	if(l == r)return;
	int mid = (l + r)>>1;
	build(l,mid,id<<1);
	build(mid+1,r,id<<1|1);
}

void push_up(int id) {
	if(tree[id].mark) {
		tree[id<<1].mark = 1;
		tree[id<<1|1].mark = 1;
		tree[id].mark = 0;

		tree[id<<1].pri = min(tree[id].pri,tree[id<<1].pri);
		tree[id<<1|1].pri = min(tree[id].pri,tree[id<<1|1].pri);
	}
}

void update(int l,int r,int id,ll cost) {
	if(l <= tree[id].l && r >= tree[id].r) {
		tree[id].pri = min(tree[id].pri,cost);
		tree[id].mark = 1;return ;
	}
	push_up(id);
	int mid = (tree[id].l + tree[id].r)>>1;
	if(r <= mid)update(l,r,id<<1,cost);
	else if(l > mid)update(l,r,id<<1|1,cost);
	else {
		update(l,mid,id<<1,cost);
		update(mid+1,r,id<<1|1,cost);
	}
}

ll query(int pos,int id) {
	if(pos == 0)return 0;
	if(tree[id].l == tree[id].r)
		return tree[id].pri;
	push_up(id);
	int mid = (tree[id].l + tree[id].r)>>1;
	if(pos <= mid) return query(pos,id<<1);
	else return query(pos,id<<1|1);
}

int main() {
	int n;
	while(scanf("%d",&n) == 1) {
		for(int i=1;i<=n;i++)
			scanf("%lld",&p[i]);
		for(int i=1;i<=n;i++)
			scanf("%lld",&t[i]);
		build(1,n,1);
		for(int i=1;i<=n;i++) {
			ll tmp = query(i-1,1);
			update(1,i + t[i] - 1,1,tmp + p[i]);
		}
		ll ans = query(n,1);
		printf("%lld\n",ans);
	}
	return 0;
}