$Sol$
乍一看就是个模拟叭,用个优先队列维护不就好了.不过这里有一个问题就是怎么解决没被切的蚯蚓的增长问题.可以这样处理,每次切一条蚯蚓,给切完之后的都减去$q$,最后输出答案时都加上$q*m$就$OK$辣.还有一个要注意的地方就是每次切蚯蚓的时候都要求出它的实际长度而不是存在优先队列里的长度.
但是这样只有$80$的样子.瞎分析一波复杂度似乎是$O(mlog_{n+m}^2)$.
考虑优化,如果能把这个$log^2$去掉就好了吖.
注意到,先被切的蚯蚓的较长的一段一定大于后被切的蚯蚓的较长的一段,先被切的蚯蚓的较短的一段一定大于后被切的较短的一段.于是不需要优先队列就可以维护单调性了.具体来说开三个数组,分别存还没被切的蚯蚓(初始数组,记得排序),被切了之后较长的那个蚯蚓,被切之后较短的蚯蚓.每次选取三个数组里最长的那个切,切完之后分别加入后面两个数组就好了不需要多余的维护.
$Code$
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<queue> #include<cmath> using namespace std; int r() { int x=0,y=1;;char ch; ch=getchar(); while(ch<'0'||ch>'9') {if(ch=='-') y=-1;ch=getchar();} while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} return x*y; } bool cmp(int x,int y) { return x>y; } int q[8000010],q1[8000010],q2[8000010]; int n,m,qq,u,v,t; double p; int a[100010]; int rem; priority_queue<int> ans; int main() { n=r();m=r();qq=r();u=r();v=r();t=r(); p=(double)u/(double)v; for(register int i=1;i<=n;i++) q[i]=r(); sort(q+1,q+n+1,cmp); int h=1; int h1=1,t1=0,h2=1,t2=0; int top; for(register int i=1;i<=m;i++) { if(h>n) {if(q1[h1]>q2[h2]) top=q1[h1++];else top=q2[h2++];} else if(q[h]>=q1[h1]&&q[h]>=q2[h2]) top=q[h++]; else if(q1[h1]>=q2[h2]) top=q1[h1++]; else top=q2[h2++]; top+=rem; int x1=floor((double)top*p),x2=top-x1; rem+=qq; x1-=rem;x2-=rem; q1[++t1]=x1;q2[++t2]=x2; if(i%t==0) printf("%d ",top); } printf("\n"); for(register int i=h;i<=n;i++) ans.push(q[i]); for(register int i=h1;i<=t1;i++) ans.push(q1[i]); for(register int i=h2;i<=t2;i++) ans.push(q2[i]); for(int i=1;ans.size();i++) { if(i%t==0) printf("%d ",ans.top()+rem); ans.pop(); } return 0; }