1A,拿来练手的好题
用一个优先队列按煮熟时间从小到大排序,被煮熟了就弹出来。
用n个vector维护每种食物的煮熟时间,显然是有序的。
用树状数组维护每种煮熟食物的数量。
每次操作前把优先队列里煮熟时间<=当前时间的弹出,BIT上+1。
每次0操作把食物塞进优先队列和vector
每次1操作先看看树状数组里有没有数,没有输出angry,有的话在树状数组上二分找到最小的数。
每次2操作先看看树状数组里有没有这一种数,有的话输出并-1,没有的话看看vector有没有,有的话输出时间差,没有的话输出angry。
没了,写得行云流水。
#include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<queue> #include<vector> #define ll long long using namespace std; const int maxn=500010; struct poi{int pos, tim;}; priority_queue<poi>q; bool operator<(poi a, poi b){return a.tim>b.tim;} int n, Q, mx, t, ty, x, l, r, T; int tree[1<<20], fir[maxn], s[maxn]; vector<int>v[maxn]; inline void read(int &k) { int f=1; k=0; char c=getchar(); while(c<‘0‘ || c>‘9‘) c==‘-‘ && (f=-1), c=getchar(); while(c<=‘9‘ && c>=‘0‘) k=k*10+c-‘0‘, c=getchar(); k*=f; } inline void add(int x, int delta){for(;x<=mx;x+=x&-x) tree[x]+=delta;} inline int query(int x){int sum=0; for(;x;x-=x&-x) sum+=tree[x]; return sum;} inline void yazid() { if(!tree[mx]) {puts("Yazid is angry."); return;} int l=0, r=mx, k=1; while(l<r) { int mid=(l+r)>>1; if(tree[mid]>=k) r=mid; else k-=tree[mid], l=mid+1; } add(l, -1); printf("%d\n", l); return; } inline void yjqqaq(int t, int id) { if(query(id)-query(id-1)) {puts("Succeeded!"); add(id, -1); return;} if(v[id].size()==fir[id]) {puts("YJQQQAQ is angry."); return;} printf("%d\n", v[id][fir[id]]-t); return; } inline void clear() { memset(tree, 0, (mx+1)<<2); memset(fir, 0, (n+1)<<2); while(!q.empty()) q.pop(); for(int i=1;i<=n;i++) v[i].clear(); } int main() { read(T); while(T--) { read(n); mx=1; while(mx<=n) mx<<=1; clear(); for(int i=1;i<=n;i++) read(s[i]); read(Q); for(int i=1;i<=Q;i++) { read(t); read(ty); while(!q.empty()) { poi now=q.top(); if(now.tim<=t) q.pop(), add(now.pos, 1), fir[now.pos]++; else break; } if(!ty) read(x), q.push((poi){x, t+s[x]}), v[x].push_back(t+s[x]); else if(ty==1) yazid(); else if(ty==2) read(x), yjqqaq(t, x); else read(l), read(r), printf("%d\n", query(r)-query(l-1)); } } }