【NOIP】提高组2016 蚯蚓

时间:2022-02-06 22:18:56

【题目链接】Universal Online Judge

【题解】本题最大的特点在于从大到小切以及切分规则一致,都是切成px和x-px。

由这两个特点很容易得到结论,后切的蚯蚓得到的px一定比先切的蚯蚓得到的px小,后切的蚯蚓得到的x-px一定比先切的蚯蚓得到的x-px小。

所以可以得到三队列做法,将原蚯蚓排序后放入A队列,将每次切分后的px放入B队尾,x-px放入C队尾。每次从ABC三队头取较大者弹出并切分,将切分后的蚯蚓放入BC队尾,整体+q转化为单点-q即可。

注意:UOJ extra test卡精度,可以将u/v直接带入主过程,就不用计算p了。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cctype>
using namespace std;
const int maxn=; int read(){
char c;int s=,t=;
while(!isdigit(c=getchar()))if(c=='-')t=-;
do{s=s*+c-'';}while(isdigit(c=getchar()));
return s*t;
}
queue<int>A,B,C;
int n,m,q,u,v,t,a[maxn];
int main(){
n=read();m=read();q=read();u=read();v=read();t=read();
for(int i=;i<=n;i++)a[i]=read();
sort(a+,a+n+);
for(int i=n;i>=;i--)A.push(a[i]);
for(int i=;i<=m;i++){
if(!A.empty()&&(A.front()>=B.front()||B.empty())&&(A.front()>=C.front()||C.empty())){
int x=A.front()+(i-)*q;A.pop();if(i%t==)printf("%d ",x);
B.push((int)(1ll*x*u/v)-i*q);C.push(x-(int)(1ll*x*u/v)-i*q);
}
else if(!B.empty()&&(B.front()>=C.front()||C.empty())){
int x=B.front()+(i-)*q;B.pop();if(i%t==)printf("%d ",x);
B.push((int)(1ll*x*u/v)-i*q);C.push(x-(int)(1ll*x*u/v)-i*q);
}
else{
int x=C.front()+(i-)*q;C.pop();if(i%t==)printf("%d ",x);
B.push((int)(1ll*x*u/v)-i*q);C.push(x-(int)(1ll*x*u/v)-i*q);
}
}
printf("\n");
for(int i=;i<=n+m;i++){
if(!A.empty()&&(A.front()>=B.front()||B.empty())&&(A.front()>=C.front()||C.empty())){
int x=A.front()+m*q;A.pop();if(i%t==)printf("%d ",x);
}
else if(!B.empty()&&(B.front()>=C.front()||C.empty())){
int x=B.front()+m*q;B.pop();if(i%t==)printf("%d ",x);
}
else{
int x=C.front()+m*q;C.pop();if(i%t==)printf("%d ",x);
}
}
printf("\n");
return ;
}