zoukankan      html  css  js  c++  java
  • LOJ#2362. 「NOIP2016」蚯蚓

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

    题目链接

    85分做法

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

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

    此做法的时间复杂度为 (mathcal O(mlog 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('
    ');
    	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('
    ');
    	while(1)
    	{
    		i++;
    		int ans=getmax();
    		if(ans==-INF) break;
    		if(i%t==0)
    		{
    			write(ans+sum);
    			putchar(' '); 
    		} 
    	}
    	return 0;
    }
    
  • 相关阅读:
    webpack基础
    LeetCode232. 用栈实现队列做题笔记
    mysql 时间加减一个月
    leetcode 1381. 设计一个支持增量操作的栈 思路与算法
    LeetCode 141. 环形链表 做题笔记
    leetcode 707. 设计链表 做题笔记
    leetcode 876. 链表的中间结点 做题笔记
    leetcode 143. 重排链表 做题笔记
    leetcode 1365. 有多少小于当前数字的数字 做题笔记
    LeetCode1360. 日期之间隔几天 做题笔记
  • 原文地址:https://www.cnblogs.com/juruo-zzt/p/13693121.html
Copyright © 2011-2022 走看看