BZOJ 1588: [HNOI2002]营业额统计 (Treap/链表)
2017-01-04 15:14
441 查看
BZOJ 1588: [HNOI2002]营业额统计
题目概述:
依次给出n日的营业额,当日的营业额波动为和当日以前的营业额差值的绝对值,特别的,第一日的营业额波动为当日营业额,求n日的最小波动之和.题目分析:
(刚学了Treap来练手……)解法一:
既然是练习Treap,那就用Treap来做吧.对于每一日,先求出它的前驱和后继,用与当前数相差小的更新答案.
注意处理没有前驱或者后继的情况.
#include<cstdio> #include<iostream> #include<algorithm> using namespace std; typedef long long ll; const ll INF=(1ll<<60); struct Node { Node* ch[2]; int key,rnd; Node(){ch[0]=ch[1]=NULL;} }*root; void rotate(Node* &u,int d) { Node* v=u->ch[d^1]; u->ch[d^1]=v->ch[d]; v->ch[d]=u;u=v; } void insert(Node* &u,int val) { if(!u) { u=new Node(); u->key=val;u->rnd=rand(); return ; } int d=val>(u->key); insert(u->ch[d],val); if((u->rnd)>(u->ch[d]->rnd)) rotate(u,d^1); } #define lc u->ch[0] #define rc u->ch[1] ll find_pre(int val)//前驱 { ll pre=-INF; Node* u=root; while(u) { if(val==(u->key)) return val; else if(val>(u->key)) pre=u->key,u=rc; else u=lc; } return pre; } ll find_nxt(int val)//后继 { ll nxt=INF; Node* u=root; while(u) { if(val==(u->key)) return val; else if(val<=(u->key)) nxt=u->key,u=lc; else u=rc; } return nxt; } ll query(ll val) { ll pre=find_pre(val); ll nxt=find_nxt(val); return min(val-pre,nxt-val); } int main() { int n,x;ll ans=0; scanf("%d%d",&n,&x); insert(root,x); ans=x;--n; while(n--) { scanf("%d",&x); ans+=query(x); insert(root,x); } printf("%lld\n",ans); return 0; }
解法二:
在网上搜题解的时候看到了,还可以用链表做.可以参见论文《基本数据结构在信息学竞赛中的应用》.
大致方法就是先将所有数存下来,排个序,用链表维护一个数的前驱和后继.
从后往前,每处理完一个数,就将该数从链表中删除.
也要注意没有前驱或者后继的情况.
#include<cstdio> #include<iostream> #include<algorithm> using namespace std; typedef long long ll; const int maxn=50000+10; struct Node { int id,val; void input(int x) { scanf("%d",&val); id=x; } bool operator < (const Node& rhs) const { return val<rhs.val; } }data[maxn]; int rnk[maxn],pre[maxn],nxt[maxn]; void link(int x) { pre[nxt[x]]=pre[x]; nxt[pre[x]]=nxt[x]; } int main() { int N; scanf("%d",&N); for(int i=1;i<=N;i++) data[i].input(i); sort(data+1,data+N+1); for(int i=1;i<=N;i++) { rnk[data[i].id]=i; pre[i]=i-1; nxt[i]=i+1; } pre[1]=nxt =-1; ll ans=data[rnk[1]].val; for(int i=N;i>1;i--) { int pos=rnk[i]; int p=pre[pos],n=nxt[pos]; if(p==-1||n==-1) ans+=abs(data[pos].val-data[p<0?n:p].val); else ans+=min(data[pos].val-data[p].val,data .val-data[pos].val); link(pos); } printf("%lld\n",ans); return 0; }
相关文章推荐
- BZOJ 1588: [HNOI2002]营业额统计 双向链表 / splay / treap
- bzoj1588 [HNOI2002]营业额统计 (treap)
- 【BZOJ 1588】[HNOI2002] 营业额统计(Treap)
- 【链表】BZOJ1588: [HNOI2002]营业额统计
- BZOJ[1588][HNOI2002]营业额统计 Treap
- 【BZOJ 1588】【HNOI 2002】营业额统计(treap模板题)
- bzoj1588 [HNOI2002]营业额统计(treap)
- 【BZOJ 1588】营业额统计 【HNOI2002】【平衡树】【双向链表】
- BZOJ 1588 HNOI2002 营业额统计 Treap
- bzoj1588 [HNOI2002]营业额统计(Treap)
- bzoj 1588: [HNOI2002]营业额统计 treap
- [BZOJ1588][HNOI2002][双向链表][SPLAY]营业额统计
- BZOJ 1588 HNOI2002 营业额统计 裸Treap
- bzoj1588[HNOI2002]营业额统计 treap
- bzoj1588[HNOI2002]营业额统计 treap
- 【Treap】BZOJ1588-[HNOI2002]营业额统计
- bzoj1588 [HNOI2002]营业额统计(Treap)
- 数据结构:(平衡树,链表)BZOJ 1588[HNOI2002]营业额统计
- [Bzoj1588][HNOI2002]营业额统计 (Treap|Splay)
- 【Treap】bzoj1588-HNOI2002营业额统计