Live2D

【NOIP2016提高组复赛】蚯蚓 题解

【NOIP2016提高组复赛】蚯蚓

Description

在这里插入图片描述

Input

在这里插入图片描述

Ouput

在这里插入图片描述

Sample Input

Sample Input1:
3 7 1 1 3 1
3 3 2

Sample Input2:
3 7 1 1 3 2
3 3 2

Sample Input3:
3 7 1 1 3 9
3 3 2

Sample Output

Sample Output1:
3 4 4 4 5 5 6
6 6 6 5 5 4 4 3 2 2
在这里插入图片描述
Sample Output2:
4 4 5
6 5 4 3 2
在这里插入图片描述
Sample Output3
2
在这里插入图片描述

分析

这题我模拟赛的时候是用了线段树调了2h之后拿了暴力分……(我太弱了)
不过好像用堆可以拿到80分的好成绩,所以如果想不到正解在考场上80分也是很可观的得分了(线段树80应该也没问题,but我……)
正解非常的巧妙:
首先我们对于两条蚯蚓:\(x1\)\(x2\),且\(x1>x2\),那么\(x1\)肯定比\(x2\)先被砍断(可怜的蚯蚓~~)
\(x1\)被砍断成两只蚯蚓\(a1\)\(b1\)长度分别为\(a1=⌊p*x1⌋\)\(b1=x1-⌊p*x1⌋\)
\(x2\)被砍断成两只蚯蚓\(a2\)\(b2\)长度分别为\(a2=⌊p*x2⌋\)\(b2=x2-⌊p*x2⌋\)
之后显然\(a1>a2\)\(b1>b2\),也就是说\(a1、b1\)一定会在\(a2、b2\)砍断之前被砍断,如果还有同学看不懂“显然”得我就来简单证明一下:
假设
砍断\(x1\)之后过了\(t\)秒后砍断\(x2\)
\(a1=⌊p*x1⌋+t∗q\)\(b2=x1−⌊p*x1⌋+t∗q\)\(x2=x2+t∗q\)
当砍断\(x2\)之后,\(a2=⌊p(x2+t*q)⌋\)\(b2=x2+t∗q−⌊p(x2+t∗q)⌋\)
然后比较\(a1\)\(a2\)的大小关系,当我们忽略下取整时,
\(a1−a2=p(x1−x2)+q∗(t−t∗p)\),又因为\(p<1\),所以这个式子的值一定是\(>0\)的,而\(b1\)\(和\)b2\(的大小关系同理 之后这道题的思路就很简单了: 我们维护三个队列: \)a[0]\(先存原来蚯蚓从大到小排序的值 \)a[1]\(存\)px\(从大到小排序的值 \)a[2]\(存\)x-px$从大到小排序的值
之后对于每次操作直接取出三个队列中最大的队首就行了

CODE

#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#define R register ll
#define N 10000005
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
ll n,m,q,u,v,t,a[3][N],head[3],tail[3];
double p;
inline void read(ll &x)
{
	x=0;int f=1;char ch=getchar();
	while (!isdigit(ch)) {if (ch=='-') f=-inf;ch=getchar();}
	while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();x*=f;
}
inline bool cmp(int a,int b) {return a>b;}
int main()
{
	freopen("earthworm.in","r",stdin);
	freopen("earthworm.out","w",stdout);
	memset(a,-inf,sizeof(a));read(n);read(m);read(q);read(u);read(v);read(t);
	for (R i=1;i<=n;++i)
		read(a[0][i]);
	sort(a[0]+1,a[0]+1+n,cmp);
	head[0]=1;tail[0]=n;head[1]=head[2]=1;tail[1]=tail[2]=0;
	for (R i=1;i<=m;++i)
	{
		ll mx=-inf,num;
		for (R j=0;j<=2;++j)
			if (a[j][head[j]]>mx) mx=a[j][head[j]],num=j;
		ll tot=mx+(i-1)*q;++head[num];if (i%t==0) printf("%lld ",tot);
		a[1][++tail[1]]=tot*u/v-i*q;
		a[2][++tail[2]]=tot-tot*u/v-i*q;
	}printf("\n");
	for (R i=1;i<=n+m;++i)
	{
		ll mx=-inf,num;
		for (R j=0;j<=2;++j)
			if (a[j][head[j]]>mx) mx=a[j][head[j]],num=j;
		ll tot=mx+m*q;++head[num];if (i%t==0) printf("%lld ",tot); 
	}printf("\n");
	return 0;
}
posted @ 2021-01-21 14:14  冷笑叹秋萧  阅读(120)  评论(0编辑  收藏  举报