zoukankan      html  css  js  c++  java
  • BZOJ1216:[HNOI2003]操作系统

    我对模拟的理解:https://www.cnblogs.com/AKMer/p/9064018.html

    题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=1216

    不兹磁多线程的系统不是好系统>_<

    对于每个进程,我们都记录下关于它的五个参数:进程号,起始时间,持续时间,终结时间以及优先级。

    按照题意,优先级越大越应优先执行,同优先级的比起始时间,用堆来维护已经进来排队的进程,然后按题意模拟即可。

    因为学长说想要(NOI)金牌,堆肯定是要会手写的,所以我一直都用手写堆,而且个人觉得(C++)(stl)除了(vector)以外都可以手动模拟的……

    时间复杂度:(O(n log n))

    空间复杂度:(O(n))

    代码如下:

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    
    const int maxn=350000;
    
    int n=1;
    
    struct AK {
    	int id,st,ed,lst,lv;
    }a[maxn];
    
    bool cmp_ed(AK a,AK b) {
    	return a.ed<b.ed;
    }
    
    bool check(int x,int y) {
    	if(a[x].lv==a[y].lv)return a[x].st<a[y].st;
    	return a[x].lv>a[y].lv;
    }//判断x进程是否比y进程优秀
    
    struct heap {
    	int tot;
    	int tree[15005];
    
    	void ins(int u) {
    		tree[++tot]=u;int now=tot;
    		while(now!=1)
    			if(check(tree[now],tree[now>>1]))
    				swap(tree[now],tree[now>>1]),now>>=1;
    			else break;
    	}//将一个元素插入堆
    
    	void pop() {
    	    tree[1]=tree[tot--];
    		int now=1;
    		while(now<<1<=tot) {
    			int son=now<<1|1;
    			if((now<<1|1)>tot||check(tree[now<<1],tree[now<<1|1]))
    			    son=now<<1;
    			if(check(tree[now],tree[son]))break;
    			else swap(tree[now],tree[son]),now=son;
    		}
    	}//从堆顶弹一个元素出去
    }T;
    
    int main() {
    	while(~scanf("%d%d%d%d",&a[n].id,&a[n].st,&a[n].lst,&a[n].lv))
    		n++;//先把所有进程都读入
    	a[n].st=2147483647;//安排一个很靠后时间进来的进程把堆里的进程全部pop出去
    	for(int i=1;i<n;i++) {
    		T.ins(i);int sum=0;//让i进程开始排队,sum为从i号进程的开始时间起已经用了多少时间
    		while(T.tot&&a[i].st+sum+a[T.tree[1]].lst<=a[i+1].st) {//如果可以把当前优先级最高的进程做完
    			sum+=a[T.tree[1]].lst;
    			a[T.tree[1]].ed=a[i].st+sum;
    		    T.pop();
    		}
    		if(T.tot)a[T.tree[1]].lst-=a[i+1].st-a[i].st-sum;//如果做不完当前优先级最高的进程,那么在下一个进程进来之前能做多少是多少
    	}
    	sort(a+1,a+n,cmp_ed);//按结束时间排序,输出答案
    	for(int i=1;i<n;i++)
    		printf("%d %d
    ",a[i].id,a[i].ed);
    	return 0;
    }
    
  • 相关阅读:
    学习笔记10-用户和组
    学习笔记9-环境变量
    学习笔记8-检测磁盘空间
    学习笔记7-监测程序
    学习笔记6-权限管理
    【数学】矩阵的逆
    【数学】矩阵
    【数学】Polya定理
    【图论】必经点和必经边
    【图论】点双连通分量
  • 原文地址:https://www.cnblogs.com/AKMer/p/9097184.html
Copyright © 2011-2022 走看看