买西瓜吃,每个西瓜有两个参数,一个是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; }
时间: 2024-12-20 07:19:51