https://vjudge.net/contest/145955#problem/C
这题朴素想法就是平衡树模拟操作一下就行了
但因为可以离线,而且前后顺序是影响先后的,所以我们可以把所有加入的人搞个离散化,值为第一关键字,进队时间为第二关键字排个序
然后他们的下标就可以体现他们的相对大小了,每个人都是不同的,而且对于相同名字不同时间进来的人,也是不同的
那么最后就是树状数组上修改查询二分一下的事情了
#include<bits/stdc++.h>
using namespace std;
const int maxl=2e5+10;
int n,m,tot;
struct mem
{
string nam;int t,val,id;
}a[maxl];
struct que
{
string op,nam;int val,rk;
}q[maxl];
int b[maxl];
map<string,int> mp;
inline bool cmp(const mem &a,const mem &b)
{
if(a.val==b.val)
return a.t>b.t;
return a.val>b.val;
}
inline void add(int i,int x)
{
while(i<=tot)
b[i]+=x,i+=i&-i;
}
inline int sum(int i)
{
int ret=0;
while(i)
ret+=b[i],i-=i&-i;
return ret;
}
inline int findk(int k)
{
int ans=0,cnt=0;
for(int i=20;i>=0;i--)
if(ans+(1<<i)<=tot && cnt+b[ans+(1<<i)]<k)
ans+=1<<i,cnt+=b[ans];
return ans+1;
}
inline void prework()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i].nam>>a[i].val;
a[i].t=i;
}
tot=n;cin>>m;
for(int i=1;i<=m;i++)
{
cin>>q[i].op>>q[i].nam;
if(q[i].op[0]=='+')
{
cin>>q[i].val;
a[++tot]=mem{q[i].nam,n+i,q[i].val,i};
}
}
sort(a+1,a+1+tot,cmp);
for(int i=1;i<=tot;i++)
if(a[i].t<=n)
{
add(i,1);
mp[a[i].nam]=i;
}
else
q[a[i].id].rk=i;
}
inline void mainwork()
{
int res=n;
for(int i=1;i<=m;i++)
if(q[i].op[0]=='+')
{
res++;add(q[i].rk,1);mp[q[i].nam]=q[i].rk;
if(res/5>(res-1)/5)
{
if(sum(q[i].rk)<=res/5)
cout<<q[i].nam<<" is working hard now."<<'\n';
else
{
cout<<q[i].nam<<" is not working now."<<'\n';
cout<<a[findk(res/5)].nam<<" is working hard now."<<'\n';
}
}
else
{
if(sum(q[i].rk)<=res/5)
{
cout<<q[i].nam<<" is working hard now."<<'\n';
cout<<a[findk(res/5+1)].nam<<" is not working now."<<'\n';
}
else
cout<<q[i].nam<<" is not working now."<<'\n';
}
}
else
{
res--;int rk=mp[q[i].nam];
if(res/5<(res+1)/5)
{
if(sum(rk)>(res+1)/5)
cout<<a[findk((res+1)/5)].nam<<" is not working now."<<'\n';
}
else
{
if(sum(rk)<=(res+1)/5)
cout<<a[findk((res+1)/5+1)].nam<<" is working hard now."<<'\n';
}
add(rk,-1);
}
}
int main()
{
prework();
mainwork();
// print();
return 0;
}