ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[NOIP2016]蚯蚓(单调性乱搞)

2019-08-13 18:51:56  阅读:219  来源: 互联网

标签:NOIP2016 队列 ++ 乱搞 int len1 read 蚯蚓


题目

链接

思路

最简单的思路肯定就是直接用堆维护,每次取最大的那一个,切成两截扔回堆里面(至于所有蚯蚓加上\(q\),可以看做是新生成的蚯蚓减去\(time*q\),最后再加回去即可,其中\(time\)即第几秒),然而这样子做是\(O(n+m)log(n+m)\)的,过不了

分析后可以发现单调性,即如果把切出来的两部分分别放到一个数组里面,它们分别单调递减

证明也很简单,设先切的蚯蚓长度为\(len1\),后切的在切\(len1\)的这个时候长度为\(len2\),那么有\(len2\)\(\leq\)\(len1\),它们长度不增长的时间仅仅是切的时候,即它们的增加量相等,那么有\(len2+c\)\(\leq\)\(len1+c\)恒成立

所以把它们分成三个数组(队列),分别存初始蚯蚓、(切了一刀之后)第一节、第二节,对初始蚯蚓排序可以使第一个数组从大到小排序,将后切出来的蚯蚓放到队列后面可以使得这两个数组也满足从大到小排序,取最大的蚯蚓即从三个队列的队头取最大值

对于第二问,将三个队列进行归并排序即可

时间复杂度为\(O(nlogn+m)\)

#include<bits/stdc++.h>
#define N 100005
#define M 7000005
using namespace std;
int n,m,q,u,v,t;
int a[3][M],top[3];
int b[N+M],c[N+M];

template <class T>
void read(T &x)
{
    char c;int sign=1;
    while((c=getchar())>'9'||c<'0') if(c=='-') sign=-1; x=c-48;
    while((c=getchar())>='0'&&c<='9') x=x*10+c-48; x*=sign;
}
bool cmp(int a,int b) {return a>b;} 
int main()
{
    read(n);read(m);read(q);
    read(u);read(v);read(t);
    for(register int i=1;i<=n;++i) read(a[0][i]);
    a[0][0]=n;
    top[0]=top[1]=top[2]=1;
    sort(a[0]+1,a[0]+n+1,cmp);
    for(register int i=1;i<=m;++i)
    {
        int maxx=(top[0]>n);
        if(a[maxx][top[maxx]]<a[1][top[1]]&&top[1]<=a[1][0]) maxx=1;
        if(a[maxx][top[maxx]]<a[2][top[2]]&&top[2]<=a[2][0]) maxx=2;
        int len=a[maxx][top[maxx]++]+(i-1)*q;
        int L=(long long)u*len/v;
        int R=len-L;
        a[1][++a[1][0]]=L-q*i;
        a[2][++a[2][0]]=R-q*i;
        if(i%t==0) printf("%d ",len);
    }
    printf("\n");
    int l=top[0],r=top[1];
    while(l<=a[0][0]&&r<=a[1][0])
    {
        if(a[0][l]>a[1][r]) b[++b[0]]=a[0][l++];
        else b[++b[0]]=a[1][r++];
    }
    while(l<=a[0][0]) b[++b[0]]=a[0][l++];
    while(r<=a[1][0]) b[++b[0]]=a[1][r++];
    l=1;r=top[2];
    while(l<=b[0]&&r<=a[2][0])
    {
        if(b[l]>a[2][r]) c[++c[0]]=b[l++];
        else c[++c[0]]=a[2][r++];
    }
    while(l<=b[0]) c[++c[0]]=b[l++];
    while(r<=a[2][0]) c[++c[0]]=a[2][r++];
    for(int i=t;i<=n+m;i+=t) printf("%d ",c[i]+m*q);
    printf("\n");
    return 0;
}

标签:NOIP2016,队列,++,乱搞,int,len1,read,蚯蚓
来源: https://www.cnblogs.com/Chtholly/p/11347779.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有