作者 杨亚
单位 北京邮电大学
三青化十大学是一所著名的大学,有着数以万计的学生。作为语文课代表,我的任务之一便是统计每位学生的试卷分数。这本来是一份不错的工作,但是令人郁闷的是,我们的孙老师为了让学生不断练习,经常给学生发卷子。如果她心情好,就给所有学生发相同数量的卷子。反之,如果心情不好,就可能收所有学生相同数量的卷子。由于她判不完这些卷子,因此学生在一段时间内都没法拿到这些卷子。
频繁收发卷子很让学生反感,尤其是收卷子的时候,一旦某位学生发现自己手中卷子数量已经低于了一名好学生应有的卷子数量,他就会立刻气愤地离开三青化十大学,并且加入北京大学邮电分校。每当一位学生离开学校,我就要从电脑中把他的学籍删去,同样,每当一名新的学生加入学校,我就得为他新建一个学籍。
孙老师经常到我这边来询问学生的情况,她并不问具体某位学生的试卷情况,而是问现在试卷数量第k多的学生手中有多少卷子。每当这时,我就不得不对数万名学生进行一次漫长的排序,然后告诉她答案。
好了,现在你已经对我的工作了解不少了。正如你猜的那样,我想请你编一个统计程序。怎么样,不是很困难吧?如果某个学生的初始试卷数量低于一名好学生应有的卷子数量,那么将不计入最后的答案内
输入格式:
第一行有两个非负整数n和min。n表示下面有多少条命令,min表示一名好学生应有的卷子数量。
接下来的n行,每行表示一条命令。命令可以是以下四种之一:
名称 格式 作用
I命令 I_k 新建一个学生学籍,初始试卷数为k。如果某学生的初始试卷数低于一名好学生应有的卷子数量,他将立刻离开学校。
A命令 A_k 给每位学生发数量k的卷子
S命令 S_k 收每位学生数量k的卷子
F命令 F_k 查询第k多的试卷数量
_(下划线)表示一个空格,I命令、A命令、S命令中的k是一个非负整数,F命令中的k是一个正整数。
在初始时,可以认为学校里一个学生也没有。
输出格式:
输出文件的行数为F命令的条数加一。
对于每条F命令,你的程序要输出一行,仅包含一个整数,为当前试卷数量第k多的学生所拥有的试卷数,如果k大于目前学生的数目,则输出-1。
输出文件的最后一行包含一个整数,为离开学校的学生的总数。
输入样例:
在这里给出一组输入。例如:
9 10
I 60
I 70
S 50
F 2
I 30
S 15
A 5
F 1
F 2
输出样例:
在这里给出相应的输出。例如:
10
20
-1
2
说明:
I命令的条数不超过100000
A命令和S命令的总条数不超过100
F命令的条数不超过100000
每次收发卷子数量不超过1000
新学生的试卷数量不超过100000
思路:
用vector模拟题目操作。
方法:
1、来人时,用二分查此人在哪个位置,插入。
2、发试卷跑单for更新。
3、收试卷时用二分去查节点。
4、查询人时直接输出。
AC代码:
#include<bits/stdc++.h> using namespace std; typedef long long ll; #define endl "\n" void solve(){ ll n,m,sum=0,cnt,c,w; string s; vector<ll>v; cin >> n >> m; while(n --){ cin >> s >> c; if(s == "I"){ if(c < m)continue; w = upper_bound(v.begin(),v.end(),c)-v.begin(); v.insert(v.begin()+w,c); } if(s == "A") for(ll i = 0 ; i < v.size() ; i ++)v[i]+=c; if(s == "S"){ w = lower_bound(v.begin(),v.end(),c+m)-v.begin(); sum+=w; v.erase(v.begin(),v.begin()+w); for(ll i = 0 ; i < v.size() ; i ++)v[i]-=c; } if(s == "F") c > v.size() ? cout << -1 << endl : cout << v[v.size()-c] << endl; } cout << sum << endl; return; } int main(){ ll t=1;//cin >> t; while(t --)solve(); return 0; }