LOJ#2362. 「NOIP2016」蚯蚓

这题做了一下午。。感谢 hxy,VoidWalker 等神仙 qaq

题目链接

85分做法

维护一个堆,里面存各个蚯蚓的长度然后按题意模拟。

对于修改每个蚯蚓长度的操作,我们并不需要在堆中一个一个修改,而是可以记录一个 \(\mathrm{sum}\),代表到当前加了多少遍 \(q\)。但如果这样存,将蚯蚓砍成两段这个操作就需要特殊处理一下,具体看代码。

此做法的时间复杂度为 \(\mathcal O(m\log n)\),可获得 85 分,开 O2 可以获得 90 分。

#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<ctime>
#include<climits>
#include<algorithm>
#include<queue>
using namespace std;
inline int read()
{
	int x=0,f=1;
	char c=getchar();
	while(c<'0' || c>'9')
	{
		if(c=='-') f=-1;
		c=getchar();
	}
	while(c>='0' && c<='9')
	{
		x=(x<<1)+(x<<3)+(c^48);
		c=getchar();
	}
	return x*f;
}
void write(int n)
{
	if(n<0)
	{
		putchar('-');
		n=-n;
	}
	if(n>9) write(n/10);
	putchar(n%10^48);
} 
int main()
{
	priority_queue<int> que;
	int n=read(),m=read(),q=read(),u=read(),v=read(),t=read();
	double p=u*1.0/v;
	for(int i=1;i<=n;i++) que.push(read());
	int sum=0;
	for(int i=1;i<=m;i++)
	{
		int x=que.top()+sum; que.pop();
		int t1=x*p,t2=x-t1;
		t1-=(sum+q);
		t2-=(sum+q);
		que.push(t1); que.push(t2);
		if(i%t==0)
		{
			write(x);
			putchar(' ');
		}
		sum+=q;
	}
	int i=0;
	putchar('\n');
	while(!que.empty())
	{
		i++;
		if(i%t==0) 
		{
			write(que.top()+sum);
			putchar(' ');
		}
		que.pop();
	}
	return 0;
}

100分做法

开三个队列,分别存蚯蚓的初始长度、砍断之后前一段的长度和砍断之后后一段的长度。通过观察,可看出这三个队列都是单调的。也就是说我们没必要开一个堆来找最长的蚯蚓,而是可以在这三个队列的队首中取 \(\max\),将这个蚯蚓砍断,然后分别存入第二、第三个队列,以此类推。这样我们就把优先队列的 \(\log\) 替换成了队列的常数,总复杂度变成了 \(\mathcal O(m)\)

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
inline int read()
{
	int x=0,f=1;
	char c=getchar();
	while(c<'0' || c>'9')
	{
		if(c=='-') f=-1;
		c=getchar();
	}
	while(c>='0' && c<='9')
	{
		x=(x<<1)+(x<<3)+(c^48);
		c=getchar();
	}
	return x*f;
}
void write(int n)
{
	if(n<0)
	{
		putchar('-');
		n=-n;
	}
	if(n>9) write(n/10);
	putchar(n%10^48);
}
using namespace std;
queue<int> que1,que2,que3;
const int INF=0X7FFFFFFF;
inline int getmax()
{
	int l1=-INF,l2=-INF,l3=-INF;
	if(!que1.empty()) l1=que1.front();
	if(!que2.empty()) l2=que2.front();
	if(!que3.empty()) l3=que3.front();
	int maxn=max(l1,max(l2,l3));
	if(maxn==-INF) return -INF;
	if(l1==maxn) que1.pop();
	else if(l2==maxn) que2.pop();
	else if(l3==maxn) que3.pop();
	return maxn;
}
int a[10000010];
int main()
{
	int n,m,q,u,v,t;
	n=read();m=read();q=read();u=read();v=read();t=read();
	double p=u*1.0/v;
	int sum=0;
	for(int i=1;i<=n;i++) a[i]=read();
	sort(a+1,a+n+1);
	for(int i=1;i<=n;i++) que1.push(a[n-i+1]);
	for(int i=1;i<=m;i++)
	{
		int x=getmax()+sum;
		int t1=x*p,t2=x-t1;
		t1-=sum+q; t2-=sum+q;
		que2.push(t1);
		que3.push(t2);
		if(i%t==0)
		{
			write(x);
			putchar(' ');
		}
		sum+=q;
	}
	int i=0;
	putchar('\n');
	while(1)
	{
		i++;
		int ans=getmax();
		if(ans==-INF) break;
		if(i%t==0)
		{
			write(ans+sum);
			putchar(' '); 
		} 
	}
	return 0;
}
posted @ 2020-09-18 19:41  zzt1208  阅读(210)  评论(1编辑  收藏  举报