模拟+优先队列
首先来分析题意
维护若干个进程(含编号pid,内存m,优先级p)
每个进程有若干个信息(含优先级p)
需要维护的信息
1.每个进程中优先级最高的信息,设其为q1[]
2.所有信息中综合优先级最高的信息,设其为q2
3.所有进程中内存最大的进程
支持的操作
1.创建
2.查询
3.删除
4.修改
简单的部分
一个优先队列维护内存最大的进程
一个优先队列数组维护每个进程的最大信息
用一个vis数组维护编号为pid的进程是否可用
这样就完成了create,message,process,kill,killmax操作
难的部分
1.如何删除:采用懒惰删除法,将优先队列中元素是否可用移到出队时判断
2.如何判断:q2中的信息是可用的:
-1- 所属进程是可用的
-2- 是所属进程中最大优先级的那个
-3- 所属进程的优先级没有更改
3.如何修改:将pid进程的优先级更改,并将q1[pid].top()插入q2
注意 修改时只更新了优先级最高的那个信息,因为暂时只有它会对q2的答案有影响,但是若最高优先级的信息被使用了,下一个优先级的信息便需要插入到q2中。也就是说,我们q2里一定保存了每个进程中优先级最高的信息(想一想,为什么)
4.关于创建,每次创建相当于改了内存和优先级,所以插入操作同修改
几个注意点
1.进程被删除后信息仍在
2.优先队列务必注意判断是否为空
3.优先队列是大根堆
复杂度分析
总共N次操作,每次往每个优先队列插入1个值,插入复杂度O(logN)
复杂度O(NlogN)
代码如下
#include<bits/stdc++.h>
using namespace std;
const int N = 100010;
struct Dte{
int i,p,ph;
bool operator < (const Dte B)const{
return (1ll*p*ph)<(1ll*B.p*B.ph);
}
};
typedef pair<int,int> pii;
priority_queue<pii,vector<pii>,greater<pii> >q1;
priority_queue<int>q2[N];
priority_queue<Dte>q3;
int n,vis[N],h[N],mem[N];
char s[20];
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%s",s+1);
//字符串的一种暴力判断方式:看各位字母
if(s[1]=='c'&&s[2]=='r'){
int i,m,p;
scanf("%d%d%d",&i,&m,&p);
if(!vis[i]){
q1.push(make_pair(-m,i));
//pair的比较是现比较第一个元素,后比较第二个元素
//优先队列是大根堆,所以m要取负数
vis[i]=1;h[i]=p;mem[i]=m;
//不空才能插入
if(!q2[i].empty())
q3.push((Dte){i,q2[i].top(),h[i]});
}
else printf("Error\n");
}
else if(s[1]=='m'){
int i,p;
scanf("%d%d",&i,&p);
if(vis[i]){
q2[i].push(p);
q3.push((Dte){i,p,h[i]});
}
else printf("Error\n");
}
else if(s[1]=='p'){
int i;
scanf("%d",&i);
if(vis[i]){
if(q2[i].empty()){printf("Empty\n");}
else{
printf("Process: %d\n",q2[i].top());
q2[i].pop();
//优先级最大的信息用了,次大的信息应加入
if(!q2[i].empty())q3.push((Dte){i,q2[i].top(),h[i]});
}
}
else printf("Error\n");
}
else if(s[1]=='r'){
if(q3.empty()){printf("Empty\n");continue;}
int flag=1;Dte now=q3.top();q3.pop();
while((!vis[now.i])||h[now.i]!=now.ph||q2[now.i].empty()||(now.p!=q2[now.i].top())){
if(q3.empty()){
printf("Empty\n");
flag=0;
break;
}
now=q3.top();q3.pop();
}
if(!flag){continue;}
printf("Run: %lld\n",1ll*now.p*now.ph);
q2[now.i].pop();
//同上
if(!q2[now.i].empty()){
q3.push((Dte){now.i,q2[now.i].top(),h[now.i]});
}
}
else if(s[1]=='c'){
int i,p;
scanf("%d%d",&i,&p);
if(vis[i]){
h[i]=p;
//这里只更新一个最大优先级的信息,确保时间复杂度
if(!q2[i].empty())q3.push((Dte){i,q2[i].top(),h[i]});
}
else printf("Error\n");
}
else if(s[1]=='k'&&s[5]=='m'){
if(q1.empty())printf("Empty\n");
else{
int pid=q1.top().second,mm=q1.top().first,flag=1;
q1.pop();
//m也要看改没改过,因为有kill操作
while((!vis[pid])||(mem[pid]!=(-mm))){
if(q1.empty()){flag=0;break;}
pid=q1.top().second;
mm=q1.top().first;
q1.pop();
}
if(flag){
printf("Kill: %d\n",pid);
vis[pid]=0;
}
else printf("Empty\n");
}
}
else if(s[1]=='k'){
int i;
scanf("%d",&i);
if(vis[i])vis[i]=0;
else printf("Error\n");
}
}
return 0;
}