您的位置:首页 > 编程语言 > C语言/C++

NOIP2016 day2 t2蚯蚓

2017-04-03 09:53 411 查看
本蒟蒻这道题结结实实做了好多遍

开始没有想到好方法,就真的打了一个大根堆,成功TLE

后来经过大佬提醒,发现只要用单调队列就可以

STL不熟练,自己打了个手写的

首先解决每次蚯蚓变长的问题。显然,如果每次都让其他蚯蚓+q,那肯定会超时。可以类比懒惰标记(别问我为什么要这样类比,反正我最开始时是这样想的。好吧,没明白的就忽视这句话好了)。定义一个变量l,l的意思是如果某蚯蚓有幸从没有被切过,那么它当前将变长的长度。每次要切一条蚯蚓时,先让他+l,再切,得到x,y。然后l+=q。这是x和y都要-l。自己想想,可以想到这样做是正确的。

定义三个队列,一个存最开始的长度(当然是按照从大到小排序后的),设被切的那一个长度是x,那么一个存xp,一个存x(1-p)。自己动脑子想想,手动列一列算一算,容易证明(不要吐槽这个万恶的词语,自己证一证,真的很容易证明)三个队列都是单调的,即当前所有蚯蚓中的最大长度是三个单调队列front的最大值。

还有if(k%t==0)可能会被卡,所以我写了一个非常丑陋的防卡常,其实不写防卡常也是可以的

这样就可以了。复杂度O(m+n);

//但是跟大佬相比还是慢一些

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int inf=-0x7f;

int read()
{
int f=1,p=0;
char c=getchar();
while(c>'9'||c<'0')
{
if(c=='-')f=-1;
c=getchar();
}
while(c>='0'&&c<='9')
{
p=p*10+c-'0';
c=getchar();
}
return f*p;
}
bool comp(int a,int b){return a>b;}
int n,m,q,u,v,t;
long long a[400010],z=1,zz=1,l;
long long o[8000100],x=1,xx=1,h[8000100],c=1,cc=1;
int check()
{
int t=1;
if(a[z]<o[x])t=2;
if(t==1&&a[z]<h[c])return 3;
if(t==2&&o[x]<h[c])return 3;
return t;
}
int main()
{
n=read(),m=read();
q=read(),u=read();
v=read(),t=read();
memset(a,inf,sizeof(a));
memset(o,inf,sizeof(o));
memset(h,inf,sizeof(h));
for(int i=1;i<=n;i++)a[i]=read();
sort(a+1,a+n+1,comp);
for(int tt,i=1;i<=m;i++)
{
long long b;
tt=check();
b=l,l+=q;
if(tt==1)b+=a[z],++z;
if(tt==2)b+=o[x],++x;
if(tt==3)b+=h[c],++c;
o[xx]=b*u/v-l,++xx;
h[cc]=b-b*u/v-l,++cc;
if(i%t==0)printf("%lld ",b);
}
printf("\n");
for(int tt,i=1;i<=m+n;i++)
{
long long b;
tt=check();
if(tt==1)b=a[z],++z;
if(tt==2)b=o[x],++x;
if(tt==3)b=h[c],++c;
if(i%t==0)printf("%lld ",b+l);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  c++ NOIP