大江东去,浪淘尽,千古风流人物。故垒西边,人道是,三国周郎赤壁。乱石穿空,惊涛拍岸,卷起千堆雪。江山如画,一时多少豪杰。遥想公瑾当年,小乔初嫁了,雄姿英发。羽扇纶巾,谈笑间,樯橹灰飞烟灭。故国神游,多情应笑我,早生华发。人生如梦,一尊还酹江月。

题解 P1486 【[NOI2004]郁闷的出纳员】

Vector大法好~

核心代码只有短短的10多行,你值得拥有

multiset捞爆了,只有40分

Vector提交记录

  • vector通过lower_bound和insert操作能够维护一个有序递减/递增的线性表

  • insert复杂度虽然是O(n),实际表现却非常快(可以看做sqrt(n)),配合lower_bound能够做到许多事情

  • 在这道题中,我们重载了lower_bound的<运算符,维护一个单调递减的序列

有两处需要注意的细节

  1. erase的复杂度为O(n),因为是区间删除,我们要避免用erase操作,注意到删除的区间是序列中最小的一段区间,考虑用O(1)的pop_back

  2. pop_back的复杂度是O(1),元素总数不超过100000,故删除操作总复杂度为O(N)

  3. 查询元素总数时,我们也不用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;
}
posted @ 2019-08-20 11:11  White_star  阅读(122)  评论(0编辑  收藏  举报
}