NOIP 2016【蚯蚓】

好吧,我承认我是个智障……
这道题一眼看上去就是个堆,然而实际上有单调性。
注意到,如果 (q = 0) 的话,将蚯蚓的左右两边分开丢进两个队列中,则两个队列都是单调不增的,因为每次取出的蚯蚓长度单调不增。
对于 (q eq 0),因为除了切开的两只,所有蚯蚓长度都增加了,我们维护这个增加的值,表示三个队列(包括初始队列)中所有的元素都要加上这个值才是真实的长度。但是这样刚切开的蚯蚓的左右两边长度就多增加了 (q),所以我们把他们的长度减 (q) 再丢进两个队列中。这样就保证了每个元素加上这个元素后就是真实的长度。
至于单调性,和 (q=0) 相比,每次只有最小的两个变得更小,而总体加上一个数是不影响单调性的,所以仍然是单调不增的。
我是个智障是因为我代码里有这样一句话:

memset(a+1,-127,sizeof(a));

于是数组越界就炸飞天了,别问我为什么,我该吃药了……

#include <bits/stdc++.h>
using namespace std;

#define ll long long
#define RG register
#define N 7100005

inline int gi()
{
	RG int ret; RG char ch;
	ret=0, ch=getchar();
	while (ch < '0' || ch > '9')
		ch=getchar();
	while (ch >= '0' && ch <= '9')
		ret=(ret<<3)+(ret<<1)+ch-'0', ch=getchar();
	return ret;
}

int a[N],l[N],r[N],ha,hl,hr,ta,tl,tr,now;

inline void get()
{
	if (a[ha] > l[hl])
		if (a[ha] > r[hr])
			now=a[ha++];
		else
			now=r[hr++];
	else
		if (l[hl] > r[hr])
			now=l[hl++];
		else
			now=r[hr++];
}

int main()
{
//	freopen("earthworm.in","r",stdin);
//	freopen("earthworm.out","w",stdout);
	int n,m,q,u,v,t,i,inc,le,ri;
	n=gi(), m=gi(), q=gi(), u=gi(), v=gi(), t=gi();
	memset(a,-127,sizeof(a));
	memset(l,-127,sizeof(l));
	memset(r,-127,sizeof(r));
	for (i=1; i<=n; ++i)
		a[i]=gi();
	sort(a+1,a+n+1,greater <int> ());
	ha=hl=hr=1, tl=tr=0, ta=n, inc=0, i=1;
	n+=m;
	while (m--)
		{
			get();
			now+=inc;
			if (i == t)
				printf("%d ",now), i=0;
			le=(ll)now*u/v, ri=now-le;
			inc+=q, i++;
			le-=inc, ri-=inc;
			l[++tl]=le, r[++tr]=ri;
		}
	putchar('
');
	i=1;
	while (n--)
		{
			get();
			if (i == t)
				i=0, printf("%d ",now+inc);
			i++;
		}
	return 0;
}
原文地址:https://www.cnblogs.com/y142857/p/7650884.html