题目大意:
n个人,m次提交,每次提交都代表某支队伍做出一题,并且给出罚时,让你输出每次提交后,编号为1的队伍的排名。
思路:
首先处理ac和罚时,由于罚时最大1000,最多有1e5次,要保证ac比罚时重要的多,所以一次ac,权值加1e8 再减 罚时。
维护一个小根堆,由于元素没有重复的,所以可以直接用set。
更新的如果是team1,把更新后的team1的权值和小根堆堆顶比较,小于等于team1的删除。
更新的如果是其他队伍,先判断是否在堆内,如果在,就先删去堆中原有的状态,再把更新后的塞回堆,如果不在堆内,就判断一下有没有比team1大,如果大于,则塞入堆内。
每次只要输出堆的大小加一就可以了。
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #include<string.h> #include<sstream> #include<set> #include<map> #include<vector> #include<queue> #include<stack> #include<bitset> #define CLR(a,b) memset((a),(b),sizeof((a))) using namespace std; typedef long long ll; inline int rd() { int f = 1; int x = 0; char s = getchar(); while (s<'0' || s>'9') { if (s == '-')f = -1; s = getchar(); } while (s >= '0'&&s <= '9') { x = x * 10 + s - '0'; s = getchar(); }x *= f; return x; } const int maxn = 100010; struct dian { ll val; int id; friend bool operator<(const dian &a, const dian &b) { if (a.val - b.val)return a.val < b.val; return a.id < b.id; } }a[maxn]; set <dian > s; struct node { int team; ll time; }op[maxn]; int n, m; int vis[maxn]; ll acp = 1e8 + 1, time , val; int team; int main() { cin >> n >> m; val = 0; for (int i = 1; i <= n; i++) { a[i].id = i; } for (int i = 1; i <= m; i++) { scanf("%d%lld", &team, &time); if (team != 1) { if (vis[team]) { s.erase(a[team]); a[team].val += acp - time; s.insert(a[team]); printf("%d ", 1 + (int)s.size()); } else { a[team].val += acp - time; if (a[team].val > val) { s.insert(a[team]); vis[team] = 1; // printf("i:%d ",i); // printf("size:%d ", s.size()); } printf("%d ", 1 + (int)s.size()); } } else { val += acp - time; set<dian >::iterator it; if (s.empty()) { printf("1 "); continue; } it = s.begin(); while (it->val <= val) { s.erase(it); vis[it->id] = 0; if (s.empty())break; it = s.begin(); } printf("%d ", 1 + (int)s.size()); } } }