描述
http://www.lydsy.com/JudgeOnline/problem.php?id=1588
给出每一天的营业值,求出之前的天当中与它相差最小的营业值与它的差的绝对值(第一天的差值为他本身),求和.
1588: [HNOI2002]营业额统计
Time Limit: 5 Sec Memory Limit: 162 MB
Submit: 12954 Solved: 4732
[Submit][Status][Discuss]
Description
营
业额统计 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况。
Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额。分析营业情况是一项相当复杂的工作。由于节假日,大减价或者是其他情况的时候,营业
额会出现一定的波动,当然一定的波动是能够接受的,但是在某些时候营业额突变得很高或是很低,这就证明公司此时的经营状况出现了问题。经济管理学上定义了
一种最小波动值来衡量这种情况: 该天的最小波动值 当最小波动值越大时,就说明营业情况越不稳定。
而分析整个公司的从成立到现在营业情况是否稳定,只需要把每一天的最小波动值加起来就可以了。你的任务就是编写一个程序帮助Tiger来计算这一个值。
第一天的最小波动值为第一天的营业额。 输入输出要求
Input
第一行为正整数 ,表示该公司从成立一直到现在的天数,接下来的n行每行有一个整数(有可能有负数) ,表示第i天公司的营业额。
Output
输出文件仅有一个正整数,即Sigma(每天最小的波动值) 。结果小于2^31 。
Sample Input
5
1
2
5
4
6
Sample Output
HINT
结果说明:5+|1-5|+|2-1|+|5-5|+|4-5|+|6-5|=5+4+1+0+1+1=12
该题数据bug已修复.----2016.5.15
Source
分析
比宠物收养所更裸,果然十几年前的题都是水吗...然而我只会做水题.
注意:
1.第一次写Splay的时候重复的元素直接跳过导致一直T,后来就先把这个值伸展上来再跳过,就过了,果然这种均摊的复杂度不是可以瞎玩的...
另外,不判重似乎慢不了多少...
2.set里写成min(*it-x,x-*(--it))会出错,可能是min函数理由什么奥妙?it多减了几次?...
3.如果set里不先加入INF和-INF的话,每次需要判断*it是不是st.end()(最后一个的后面),st.begin()(第一个).
Treap:
#include <cstdio>
#include <cstdlib>
#include <algorithm>
using namespace std; const int oo=~0u>>; struct Treap{
struct node{
node* ch[];
int v,r;
node(int v,node* t):v(v){ ch[]=ch[]=t; r=rand(); }
}* root,* null;
Treap(){
null=new node(,NULL); null->r=oo;
root=null;
}
void rot(node* &o,bool d){
node* k=o->ch[!d]; o->ch[!d]=k->ch[d]; k->ch[d]=o;
o=k;
}
void insert(node* &o,int x){
if(o==null) o=new node(x,null);
else{
if(x==o->v) return;
bool d=x>o->v;
insert(o->ch[d],x);
if(o->ch[d]->r<o->r) rot(o,!d);
}
}
int pre(node* o,int x){
if(o==null) return -oo;
if(o->v<=x) return max(pre(o->ch[],x),o->v);
return pre(o->ch[],x);
}
int suc(node* o,int x){
if(o==null) return oo;
if(o->v>=x) return min(suc(o->ch[],x),o->v);
return suc(o->ch[],x);
}
}tree; int n,a,ans; int main(){
scanf("%d",&n);
scanf("%d",&a);
ans+=a; tree.insert(tree.root,a); n--;
while(n--){
if(scanf("%d",&a)==EOF) a=;
int pre=tree.pre(tree.root,a);
int suc=tree.suc(tree.root,a);
if(pre==-oo) ans+=suc-a;
else if(suc==oo) ans+=a-pre;
else ans+=min(suc-a,a-pre);
tree.insert(tree.root,a);
}
printf("%d\n",ans);
return ;
} Treap
Splay:
#include <cstdio>
#include <algorithm>
using namespace std; const int oo=~0u>>; struct Splay{
struct node{
node* ch[],*pa;
int v;
node(int v,node* t):v(v){ ch[]=ch[]=pa=t; }
bool d(){ return pa->ch[]==this; }
void setc(node* t,bool d) { ch[d]=t; t->pa=this; }
}*root,*null;
Splay(){
null=new node(,NULL);
root=null;
}
void rot(node* o){
node* pa=o->pa; bool d=o->d();
pa->pa->setc(o,pa->d());
pa->setc(o->ch[!d],d);
o->setc(pa,!d);
if(pa==root) root=o;
}
void splay(node* o,node* pa){
while(o->pa!=pa){
if(o->pa->pa==pa) rot(o);
else o->d()==o->pa->d()?(rot(o->pa),rot(o)):(rot(o),rot(o));
}
}
void insert(int x){
if(root==null){ root=new node(x,null); return; }
node* t=root;
if(t->v==x) return;
while(t->ch[x>t->v]!=null&&t->ch[x>t->v]->v!=x) t=t->ch[x>t->v];
if(t->ch[x>t->v]!=null){ splay(t->ch[x>t->v],null); return; }
node* k=new node(x,null);
t->setc(k,x>t->v);
splay(k,null);
}
int pre(int x){
node* t=root;
int ret=-oo;
while(t!=null){
if(t->v==x) return x;
if(t->v<x) ret=t->v,t=t->ch[];
else t=t->ch[];
}
return ret;
}
int suc(int x){
node* t=root;
int ret=-oo;
while(t!=null){
if(t->v==x) return x;
if(t->v>x) ret=t->v,t=t->ch[];
else t=t->ch[];
}
return ret;
}
}tree; int n,a,ans; int main(){
scanf("%d",&n);
scanf("%d",&a);
ans+=a; tree.insert(a); n--;
while(n--){
if(scanf("%d",&a)==EOF) a=;
int pre=tree.pre(a);
int suc=tree.suc(a);
if(pre==-oo) ans+=suc-a;
else if(suc==-oo) ans+=a-pre;
else ans+=min(suc-a,a-pre);
tree.insert(a);
}
printf("%d\n",ans);
return ;
}
set:
#include <bits/stdc++.h>
using namespace std; const int INF=0x3fffffff;
int n,x,ans;
set <int> st;
int main(){
scanf("%d",&n);
st.insert(INF); st.insert(-INF);
scanf("%d",&x); ans=x; st.insert(x);
set <int> :: iterator it;
for(int i=;i<n;i++){
scanf("%d",&x);
it=st.lower_bound(x);
int a=*it-x,b=x-*(--it);
int ret=min(a,b);
if(ret) ans+=ret, st.insert(x);
}
printf("%d\n",ans);
return ;
}