BZOJ 4721: [Noip2016]蚯蚓 乱搞

4721: [Noip2016]蚯蚓

Time Limit: 10 Sec  Memory Limit: 512 MB
Submit: 1220  Solved: 298
[Submit][Status][Discuss]

Description

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

Input

第一行包含六个整数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<=10^5,0<m<7*10^6,0<u<v<10^9,0<=q<=200,1<t<71,0<ai<10^8。

Output

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

Sample Input

3 7 1 1 3 1
3 3 2

Sample Output

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


先说

在BZOJ狂PE不止(行尾不能有空格,最后不能有回车)给一百个差评

强烈建议去交 UOJ #264. 【NOIP2016】蚯蚓

要不然根本不知道错哪里


想起去年什么都不会的我,在考场上研究究好久

最后一分没得,括弧泪

那时连题解都看不懂,别提改了

今天就要了却遗恨


好,该说一说题解啦

我们发现

对于两条先后被切开的蚯蚓a,b,分别分开两段

若a>=b

一定有a*u/v>=b*u/v

那么对于两对,如果分别推进队列里,一定是单调递减的

那么又出现了新的问题

没被切的蚯蚓在每一秒都会长长,而被切的蚯蚓却没长

如何保障单调性呢

设中间相隔k次操作

证明

a*u/v+k*q>=(b+k*q)*u/v

好像因为之前的铺垫使得这一步不证自明。。。

建议手玩一下

像我这种SB脑洞模拟的时候竟然证明了它是错的。。。

我们已经知道了它的正确性

所以直接开三个队列

第一个放初始

第二个放切开后较大的

第三个放切开后较小的

最后三路归并就好了


#include<cmath>
#include<ctime>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<complex>
#include<iostream>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<string>
#include<bitset>
#include<queue>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
inline ll read()
{
	ll x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch<='9'&&ch>='0'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
	return x*f;
}
const int N=7100100;
ll q[N][3],a[N],m,n,t,u,v;
inline bool cmp(ll x,ll y)
{return x>y;}
int main()
{
	n=read();m=read();int p=read();u=read();v=read();int t=read();
	int head[3]={1,1,1},tail[3]={1,1,1};
	for(int i=1;i<=n;i++)a[i]=read();
	sort(a+1,a+1+n,cmp);
	for(int i=1;i<=n+m;i++)q[i][0]=q[i][1]=q[i][2]=-0X3f3f3f3f;
	for(int i=1;i<=n;i++)q[tail[0]++][0]=a[i];
	ll pl=0;
	for(int i=1,l,r,now;i<=m;i++)
	{
		now=0;
		if(q[head[0]][0]<q[head[1]][1])now=1;
		if(q[head[now]][now]<q[head[2]][2])now=2;
		q[head[now]][now]+=pl;
		pl+=p;if(i%t==0&&i+t<=m)printf("%lld ",q[head[now]][now]);else if(i%t==0&&i+t>m)printf("%lld",q[head[now]][now]);
		l=q[head[now]][now]*u/v;r=q[head[now]][now]-l;
		if(l>r)swap(l,r);l-=pl;r-=pl;
		head[now]++;
		q[tail[1]++][1]=r;
		q[tail[2]++][2]=l;
	}
	puts("");ll ans;
	for(int i=1,now=0;i<=m+n;i++)
	{
		if(head[0]<tail[0])now=0;
		if(head[1]<tail[1])if(q[head[now]][now]<q[head[1]][1])now=1;
		if(head[2]<tail[2])if(q[head[now]][now]<q[head[2]][2])now=2;
		ans=q[head[now]][now]+pl;head[now]++;
		if(i%t==0&&i+t<=n+m)printf("%lld ",ans);else if(i%t==0&&i+t>n+m)printf("%lld",ans);
	}
	return 0;
}
/*
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
*/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值