P2827 蚯蚓
AC代码:
/* 思路:三队列模拟。 第一个队列存放原始的蚯蚓长度(已从大到小排序)。 第二个队列存放蚯蚓被切后的一份的长度([px])。 第三个队列存放蚯蚓被切后的另一份的长度(x-[px])。 每次在三个队列的队头中取一个最大值并将其出队,然后将其分成两份分别存在第二、三个队列里。 因为每一次我们都是切最长的,而当我们切下一条时两条原来属于上一条的蚯蚓又会增长, 所以先切一定大于后切的,第二、三个队列也就是单调递减的了。 除此之外,还要加一个标记,记录当前每一条蚯蚓应增加的长度,操作时就加上,入队时就减去,输出时也要加上, 这样就不用一个一个加了。 */ #include<iostream> #include<cstdio> #include<fstream> #include<algorithm> #include<string> #include<sstream> #include<cstring> using namespace std; struct duilie//手打队列 { int head;//队首 int tail;//队尾 int d[7100005];//队列 }dl[3]; int main() { dl[0].head=dl[1].head=dl[2].head=1;//初始化队首队尾 dl[0].tail=dl[1].tail=dl[2].tail=1; int n=0,m=0,q=0,t=0,k=0; double u=0,v=0; scanf("%d%d%d%lf%lf%d",&n,&m,&q,&u,&v,&t); for(int i=1;i<=n;i++) { int a=0; scanf("%d",&a); dl[0].d[dl[0].tail++]=a;//入队 } sort(dl[0].d+dl[0].head,dl[0].d+dl[0].tail,greater<int>());//从大到小排序 for(int i=1;i<=m;i++) { int x=-2147483647,y=0,l1=0,l2=0; for(int j=0;j<3;j++)//在三个队首中取最大值 if(dl[j].head<dl[j].tail&&dl[j].d[dl[j].head]>x) { x=dl[j].d[dl[j].head]; y=j; } dl[y].head++;//将最大值出队 x+=k;//加上当前标记 k+=q;//更新标记 l1=x*(u/v);//计算一段蚯蚓的长度 l2=x-l1;//计算另一段蚯蚓的长度 dl[1].d[dl[1].tail++]=l1-k;//分别入队 dl[2].d[dl[2].tail++]=l2-k; if(i%t==0) printf("%d ",x);//同时输出这一秒切的蚯蚓的长度 } printf("\n");//记得换行 for(int i=1;i<=n+m;i++)//输出m秒后每只蚯蚓的长度 { int x=-2147483647,y=0; for(int j=0;j<3;j++)//在队首中取最大值 if(dl[j].head<dl[j].tail&&dl[j].d[dl[j].head]>x) { x=dl[j].d[dl[j].head]; y=j; } dl[y].head++;//将最大值出队 if(i%t==0) printf("%d ",x+k);//输出 } printf("\n");//记得换行 return 0; }
80分优先队列代码:(注意:手打堆会更快一些,能拿到85分或以上,原理跟优先队列一样)
/*80分思路:弄一个优先队列,不停地模拟,切蚯蚓时就将最长的那一条出队, 然后一分为二入队,简单模拟即可。还要弄一个标记,表示从开始到当前时间每 一条蚯蚓应该加上的长度,操作时就加上,入队时就减去,输出时也要加上,这 样就不用一个一个加了。 */ #include<iostream> #include<cstdio> #include<fstream> #include<algorithm> #include<string> #include<sstream> #include<cstring> #include<queue> using namespace std; priority_queue<int> d; int main() { int n=0,m=0,q=0,t=0,k=0; double u=0,v=0; scanf("%d%d%d%lf%lf%d",&n,&m,&q,&u,&v,&t); for(int i=1;i<=n;i++) { int a=0; scanf("%d",&a); d.push(a);//入队 } for(int i=1;i<=m;i++) { int w=d.top(),l1=0,l2=0; d.pop(); w+=k;//加上标记 k+=q;//更新标记 l1=w*(u/v);//计算长度 l2=w-l1; d.push(l1-k);//一分为二入队 d.push(l2-k); if(i%t==0) printf("%d ",w);//同时输出这一秒切的蚯蚓的长度 } printf("\n");//换行 for(int i=1;i<=n+m;i++) { if(i%t==0) printf("%d ",d.top()+k);//输出m秒后每一条蚯蚓的长度 d.pop();//队首元素出队 } printf("\n");//换行 return 0; }