题解 P1486 【[NOI2004]郁闷的出纳员】
Vector大法好~
核心代码只有短短的10多行,你值得拥有
multiset捞爆了,只有40分
Vector提交记录
-
vector通过lower_bound和insert操作能够维护一个有序递减/递增的线性表
-
insert复杂度虽然是O(n),实际表现却非常快(可以看做sqrt(n)),配合lower_bound能够做到许多事情
-
在这道题中,我们重载了lower_bound的<运算符,维护一个单调递减的序列
有两处需要注意的细节
-
erase的复杂度为O(n),因为是区间删除,我们要避免用erase操作,注意到删除的区间是序列中最小的一段区间,考虑用O(1)的pop_back
-
pop_back的复杂度是O(1),元素总数不超过100000,故删除操作总复杂度为O(N)
-
查询元素总数时,我们也不用STL的size()(单次复杂度O(N)),而是手动维护一个siz变量
const int inf=0x3f3f3f3f,N=1e5+10;
int n,dn,delta=0,siz=0;
vector<int>s;
typedef vector<int>::iterator It;
bool cmp(const int &a,const int &b){return a>b;}
int main(){
//fin;fout;
read(n),read(dn);
char op;int x;
int ans=0;
go(i,1,n){
cin>>op;
read(x);
switch(op){
case 'I':if(x>=dn) s.insert(lower_bound(s.begin(),s.end(),x-delta,cmp),x-delta),siz++;break;
case 'A':delta+=x;break;
case 'S':{
delta-=x;
int it=upper_bound(s.begin(),s.end(),dn-delta,cmp)-s.begin();
while(siz!=it) s.pop_back(),ans++,siz--;
break;
}
case 'F':{
if(siz<x) puts("-1");
else{
printf("%d\n",s[x-1]+delta);
}
break;
}
}
}
printf("%d",ans);
return 0;
}