zoukankan      html  css  js  c++  java
  • NOIP201609蚯蚓

    【问题描述】

    本题中,我们将用符号⌊c⌋表示对c向下取整,例如:⌊3.0⌋=⌊3.1⌋=⌊3.9⌋=3
    蛐蛐国最近蚯蚓成灾了!隔壁跳蚤国的跳蚤也拿蚯蚓们没办法,蛐蛐国王只好去请神刀手来帮他们消灭蚯蚓。
    蛐蛐国里现在共有n只蚯蚓(n为正整数)。每只蚯蚓拥有长度,我们设第 ii 只蚯蚓的长度为ai (i=1,2,…,n),并保证所有的长度都是非负整数(即:可能存在长度为0的蚯蚓)。
    每一秒,神刀手会在所有的蚯蚓中,准确地找到最长的那一只(如有多个则任选一个)将其切成两半。神刀手切开蚯蚓的位置由常数p(是满足0<p<1的有理数)决定,设这只蚯蚓长度为x,神刀手会将其切成两只长度分别为⌊px⌋x−⌊px⌋的蚯蚓。特殊地,如果这两个数的其中一个等于0,则这个长度为0的蚯蚓也会被保留。此外,除了刚刚产生的两只新蚯蚓,其余蚯蚓的长度都会增加q(是一个非负整常数)。
    蛐蛐国王知道这样不是长久之计,因为蚯蚓不仅会越来越多,还会越来越长。蛐蛐国王决定求助于一位有着洪荒之力的神秘人物,但是救兵还需要m秒才能到来……(m为非负整数)
    蛐蛐国王希望知道这m秒内的战况。具体来说,他希望知道:
    m秒内,每一秒被切断的蚯蚓被切断前的长度(有m个数);
    m秒后,所有蚯蚓的长度(有n+m个数)。
    蛐蛐国王当然知道怎么做啦!但是他想考考你……

    【输入格式】

    第一行包含六个整数n,m,q,u,v,t,其中:n,m,q的意义见问题描述;
    u,v,t均为正整数;你需要自己计算p=u/v (保证0<u<v) t是输出参数,其含义将会在输出格式中解释。
    第二行包含n个非负整数,为ai,a2,...,an,即初始时n只蚯蚓的长度。
    同一行中相邻的两个数之间,恰好用一个空格隔开。
    保证1<=n<=105,0<m<7*106,0<u<v<109,0<=q<=200,1<t<71,0<ai<108

    【输出格式】

    第一行输出[m/t]个整数,按时间顺序,依次输出第t秒,第2t秒,第3t秒……被切断蚯蚓(在被切断前)的长度。
    第二行输出[(n+m)/t]个整数,输出m秒后蚯蚓的长度;需要按从大到小的顺序
    依次输出排名第t,第2t,第3t……的长度。
    同一行中相邻的两个数之间,恰好用一个空格隔开。即使某一行没有任何数需要 输出,你也应输出一个空行。
    请阅读样例来更好地理解这个格式。

    【样例输入】

    3 7 1 1 3 1
    3 3 2

    【样例输出】

    3 4 4 4 5 5 6
    6 6 6 5 5 4 4 3 2 2

    【数据范围】

    1<=n<=105,0<m<7*106,0<u<v<109,0<=q<=200,1<t<71,0<ai<108

    【题解】

    考场上的时候没想出正解,写了个优先队列骗分,结果测评机跑的太慢了......
    其实这道题正解也是挺好想的。首先先考虑蚯蚓不会变长的情况,也就是q=0的情况。
    这种情况下,因为被切的蚯蚓的长度只会越来越小,所以如果不考虑切开变出的蚯蚓,那么就是把原来的蚯蚓从大到小一条一条切掉就好了。
    但是,因为还会生成新的蚯蚓,若是再把新蚯蚓放到原来的里面再排序就多了一个log,显然不行。
    所以,可以开三个队列,把原来的蚯蚓从大到小丢到第一个队列里,把切开的两条把大的丢到一个队列里,小的丢到一个队列里。
    这样的话,因为被切的蚯蚓的长度只会越来越小,所以每个队列里的蚯蚓都是长度递减的。
    此时,我们只需要把三个队列的队首中取一个最大的丢出来,再切开丢回去就好了。

    那么,要是蚯蚓在不断地增长,以上的情况依然成立。唯一的不同就是,切出来的两条蚯蚓不变随之长。
    于是,我们用一个数来记录此时蚯蚓如果没有被切变长了多少。而对于被切掉的蚯蚓,没有增加长度其实就等价于长度减少了。
    于是,我们在把它丢回去的时候长度减少一下就可以了。
    然后,对于每条被拿出来的蚯蚓,先算出他原本的长度,再算出切开的长度,再减掉不该增长的长度丢到其他两个队列里,就搞定了。
    因此,队列里的数很可能很小,而且还会有负数,所以在比大小的时候要把初值赋为-1<<31。
    (就因为我第一次初值赋的是-1<<30,以至于在UOJ上被hack了......)

    【代码】

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #include<queue>
    using namespace std;
    #define ll long long
    #define f(i,n) for(int i=1;i<=(n);i++)
    #define N 100010
    int read()
    {
    	int x=0,f=1;char c=getchar();
    	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
    	while( isdigit(c)){x=x*10+c-'0';c=getchar();}
    	return x*f;
    }
    int n,m,q,u,v,t;
    queue<int> q1,q2,q3;
    int tag;
    int a[N];
    int qj(int i)
    {
    	int s=-1<<31;
    	if(!q1.empty())s=max(s,q1.front());
    	if(!q2.empty())s=max(s,q2.front());
    	if(!q3.empty())s=max(s,q3.front());
    	if(!q1.empty()&&s==q1.front())q1.pop();
    	else if(!q2.empty()&&s==q2.front())q2.pop();
    	else if(!q3.empty()&&s==q3.front())q3.pop();
    	s+=tag;
    	if(i%t==0)printf("%d ",s);
    	return s;
    }
    int main()
    {
    	n=read(),m=read(),q=read(),u=read(),v=read(),t=read();
    	f(i,n)a[i]=read();
    	sort(a+1,a+n+1);
    	for(int i=n;i>=1;i--)q1.push(a[i]);
    	f(i,m)
    	{
    		int s=qj(i);
    		int s1,s2;
    		s1=(ll)s*u/v;
    		s2=s-s1;
    		q2.push(max(s1,s2)-q-tag);
    		q3.push(min(s1,s2)-q-tag);
    		tag+=q;
    	}
    	printf("
    ");
    	f(i,n+m)int s=qj(i);
    }
    
  • 相关阅读:
    Typescript---01 数据类型
    微信小程序开发01 --- 微信小程序项目结构介绍
    C# 高级编程05----常用修饰符
    C# 高级编程04----类
    C# 高级编程02----手动创建C#程序
    C# 高级编程03----细节内容
    C# 高级编程01----.Net基础介绍
    Docker----起步(2)----在Ubuntu上安装最新版的Docker CE
    Microsoft Graph API -----起题 Graph API
    Docker----与Asp.net core 的完美结合,在docker容器中创建Asp.Net Core 项目
  • 原文地址:https://www.cnblogs.com/qwerfcxs/p/7814251.html
Copyright © 2011-2022 走看看