操作系统题解

题面

模拟+优先队列
首先来分析题意

维护若干个进程(含编号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;
}

转载于:https://www.cnblogs.com/zty111/p/11444227.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值