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("\n");
	f(i,n+m)int s=qj(i);
}
posted @ 2017-11-10 13:49  qwerfcxs  阅读(157)  评论(0编辑  收藏  举报