• [BZOJ5179] JSOI2011 任务调度


    问题描述

    一台超级计算机共有N颗CPU。现在这台超级计算机有M个任务要做,但同时还要考虑到不能让CPU过热。所幸的是这台超级计算机已经将任务安排好了,现在要做的只是请你根据安排好的指令来模拟它的工作过程。一开始,这N颗CPU都没有被分配任何的任务。之后,会给你以下几类指令(CPU的编号为1到N的整数,任务的编号为1到M的整数)

    指令格式 作用

    ADD n k w 将 k 号任务(权值为 w)分配给 n 号 CPU

    DEC n k w 将 k 号任务的权值减少 w(已知 k 号任务被分配给了 n 号 CPU)

    TRANS n1 n2 将分配给 n1 号 CPU 的任务全部转移给 n2 号 CPU

    MIN n 输出分配给 n 号 CPU 的任务中权值最小的任务的权值

    WORK n w 将分配给 n 号 CPU 的任务中权值最小的任务的权值加上 w,如果权值最小的任务不唯一,则不更 改权值,并输出一行“ ERROR”

    输入格式

    包含N+1行。

    第1行包含三个正整数N、M、K,分别表示CPU的数目、任务数和指令数。

    第2行到K+1行,每行包含一条指令。

    N≤500, M≤300000, K≤300000。

    保证任务的权值在 32 位有符号整型的范围内。

    保证一个任务只会被分配一次(即至多被 ADD 一次)。

    保证 ADD 指令、DEC 指令和 WORK 指令中的 w 是非负整数。

    保证 TRANS 指令的两个参数不相同。

    输出格式

    若干行,其中包括MIN语句的输出和“ERROR”输出,每个输出占一行

    样例输入

    2 3 13
    ADD 1 2 100
    ADD 1 1 90
    MIN 1
    WORK 1 20
    TRANS 1 2
    MIN 2
    ADD 1 3 105
    TRANS 2 1
    MIN 1
    DEC 1 3 200
    MIN 1
    DEC 1 1 205
    WORK 1 15

    样例输出

    90
    100
    100
    -95
    ERROR

    链接

    BZOJ

    解析

    左偏树细节操作题。我们对每一个CPU维护一个小根可并堆,对于每一个操作,我们有如下做法:

    ADD操作:就是正常的往可并堆中加入一个数。

    DEL操作:可以这么做,首先把k节点从左偏树中抠出来,即把他的两个儿子合并后接到k节点的父亲上(k是根节点时例外)。然后对k的权值进行修改,再把他加入原来所在的堆中。

    TRANS操作:即将n1合并到n2去,并把n1对应的堆设为0。

    MIN操作:查询堆顶元素值即可。

    WORK操作:相当于DEL操作,只需要细微的修改。注意,如果n的最小值与任意一个儿子所在的树中的最小值相等,说明最小值不止一个,需要输出ERROR。

    代码

    #include <iostream>
    #include <cstdio>
    #define N 502
    #define M 300002
    using namespace std;
    char op[10];
    int n,m,k,i,val[M],son[M][2],dis[M],fa[M],r[N];
    int merge(int x,int y)
    {
    	if(!x) return y;
    	if(!y) return x;
    	if(val[x]>val[y]) swap(x,y);
    	son[x][1]=merge(son[x][1],y);
    	if(dis[son[x][0]]<dis[son[x][1]]) swap(son[x][0],son[x][1]);
    	fa[son[x][0]]=fa[son[x][1]]=x;
    	dis[x]=dis[son[x][1]]+1;
    	return x;
    }
    void add(int x,int y,int z)
    {
    	int f=fa[y],tmp=merge(son[y][0],son[y][1]);
    	if(r[x]==y) r[x]=tmp;
    	else if(son[f][0]==y) son[f][0]=tmp;
    	else son[f][1]=tmp;
    	fa[tmp]=f;
    	fa[y]=son[y][0]=son[y][1]=0;
    	val[y]+=z;
    	r[x]=merge(r[x],y);	
    }
    int main()
    {
    	scanf("%d %d %d",&n,&m,&k);
    	for(i=1;i<=k;i++){
    		int x,y,z;
    		scanf("%s",op);
    		if(op[0]=='A'){
    			scanf("%d %d %d",&x,&y,&z);
    			val[y]=z;
    			r[x]=merge(r[x],y);
    		}
    		else if(op[0]=='D'){
    			scanf("%d %d %d",&x,&y,&z);
    			add(x,y,-z);
    		}
    		else if(op[0]=='T'){
    			scanf("%d %d",&x,&y);
    			r[y]=merge(r[x],r[y]);
    			r[x]=0;
    		}
    		else if(op[0]=='M'){
    			scanf("%d",&x);
    			printf("%d
    ",val[r[x]]);
    		}
    		else{
    			scanf("%d %d",&x,&y);
    			if((son[r[x]][0]&&val[r[x]]==val[son[r[x]][0]])||(son[r[x]][1]&&val[r[x]]==val[son[r[x]][1]])) puts("ERROR");
    			else add(x,r[x],y);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    Jedis API操作Redis数据库
    Go开发环境安装与环境变量配置
    Java中使用md5进行hash运算
    oracle创建表空间、用户
    CentOS安装MySQL
    Go语言之快速排序
    软件包管理rpm和yum
    第十一节:configParse模块
    redis数据库
    tcpdump命令
  • 原文地址:https://www.cnblogs.com/LSlzf/p/12244287.html
Copyright © 2020-2023  润新知