洛谷P2827 蚯蚓
pts85/90(90应该是个意外,第一次交是90之后都是85了):
优先队列模拟题意
#include<iostream> #include<cstdio> #include<queue> using namespace std; int n,m,q,u,v,t,tim; double p; priority_queue<int>qq; int main() { scanf("%d%d%d%d%d%d",&n,&m,&q,&u,&v,&t); p=1.0*u/(1.0*v); for(int i=1,x;i<=n;i++){ scanf("%d",&x); qq.push(x); } while(m--){ tim++; int x=qq.top(); qq.pop(); if(tim%t==0)printf("%d ",x+(tim-1)*q); int y=(int)(p*(double)(x+(tim-1)*q)); x=(x+(tim-1)*q)-y; qq.push(x-tim*q),qq.push(y-tim*q); } printf("\n"); int now=0; while(qq.size()){ now++; if(now%t==0){ printf("%d ",qq.top()+tim*q); } qq.pop(); } return 0; }
顺手练一下手写二叉堆
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; int n,m,q,u,v,t,tim,a[16*1000010],num; double p; bool cmp(int x,int y){ return x>y; } int main() { scanf("%d%d%d%d%d%d",&n,&m,&q,&u,&v,&t); p=1.0*u/(1.0*v); for(int i=1,x;i<=n;i++){ scanf("%d",&a[i]); x=i; while(x>1&&a[x]>a[x>>1]){ swap(a[x],a[x>>1]); x>>=1; } } while(m--){ tim++; int x=a[1]; if(tim%t==0)printf("%d ",x+(tim-1)*q); int y=(int)(p*(double)(x+(tim-1)*q)); x=(x+(tim-1)*q)-y; a[1]=x-tim*q; int now=1; while((a[now]<a[now<<1]||a[now]<a[now<<1|1])&&(now<<1|1)<=n){ if(a[now<<1]<a[now<<1|1]){ swap(a[now],a[now<<1|1]); now<<=1; now|=1; } else{ swap(a[now],a[now<<1]); now<<=1; } } if(a[now]<a[now<<1]&&(now<<1)<=n){ swap(a[now],a[now<<1]); } a[++n]=y-tim*q; now=n; while(now>1&&a[now]>a[now>>1]){ swap(a[now],a[now>>1]); now>>=1; } } printf("\n"); sort(a+1,a+n+1,cmp); for(int i=1;i<=n;i++){ if(i%t==0){ printf("%d ",a[i]+tim*q); } } return 0; }
正解:
发现先切的蚯蚓产生的长段永远不小于后切的蚯蚓产生的长段,短段也是。因为从准备切先切的开始,后切的生长t个单位长度的同时,先前切好的两段都生长了t-1个单位长度。
切好的长段集合和短段集合本身就具有单调性。
用三个队列分别储存未切的,切好的长段,切好的短段,每次从三个队头寻找最大的进行操作。
#include<iostream> #include<cstdio> #include<queue> #include<algorithm> using namespace std; int n,m,q,u,v,t,tim,maxx,pos,a[8*1000010],inf=214748364; double p; queue<int>qq[3]; bool cmp(int x,int y){ return x>y; } int main() { scanf("%d%d%d%d%d%d",&n,&m,&q,&u,&v,&t); p=1.0*u/(1.0*v); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); } sort(a+1,a+n+1); for(int i=n;i>=1;i--)qq[0].push(a[i]); while(m--){ tim++; maxx=pos=-inf; if(qq[0].front()>maxx&&qq[0].size())maxx=qq[0].front(),pos=0; if(qq[1].front()>maxx&&qq[1].size())maxx=qq[1].front(),pos=1; if(qq[2].front()>maxx&&qq[2].size())maxx=qq[2].front(),pos=2; qq[pos].pop(); if(tim%t==0)printf("%d ",maxx+(tim-1)*q); int y=(int)(p*(double)(maxx+(tim-1)*q)); maxx=(maxx+(tim-1)*q)-y; qq[1].push(max(maxx,y)-tim*q),qq[2].push(min(maxx,y)-tim*q); } printf("\n"); n=0; while(qq[0].size()){ a[++n]=qq[0].front(); qq[0].pop(); } while(qq[1].size()){ a[++n]=qq[1].front(); qq[1].pop(); } while(qq[2].size()){ a[++n]=qq[2].front(); qq[2].pop(); } sort(a+1,a+n+1,cmp); for(int i=1;i<=n;i++){ if(i%t==0){ printf("%d ",a[i]+tim*q); } } return 0; }