题目:https://www.luogu.org/problemnew/show/P2827
思路...
用优先队列模拟做的话,时间主要消耗在每次的排序上;
能不能不要每次排序呢?
关注先后被砍的两条蚯蚓 x 和 y,发现砍完以后,它们的两部分对应还满足原来的大小关系!
从两条蚯蚓出发,可以推知所有蚯蚓砍完以后的两部分还对应满足原来的大小关系;
但两部分之间就不一定了;
所以开三个队列,分别记录原来的蚯蚓,砍后第一部分的蚯蚓,砍后第二部分的蚯蚓;
每次取三个队列中最长的蚯蚓砍,砍出来的两部分对应加到砍后的两个队列里;
即使是又砍了已经被砍过的蚯蚓,把它类比成原来的蚯蚓,也满足刚才的那种做法;
于是这题就A了;
有不少细节呢,而且注意要开 long long !以后应该对这些敏感一点;
由这题得到的经验是,遇到关于询问大小关系,没有规律,需要不断排序的问题的时候,关注相邻的两个量的变化关系,也许能有意想不到的发现。
代码如下:
#include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<algorithm> #include<cmath> using namespace std; typedef long long ll; queue<pair<ll,int> >q1,q2,q3; priority_queue<int>ans; int const maxn=1e5+5; int n,m,q,u,v,t,a[maxn]; int main() { scanf("%d%d%d%d%d%d",&n,&m,&q,&u,&v,&t); for(int i=1;i<=n;i++)scanf("%d",&a[i]); sort(a+1,a+n+1); for(int i=n;i;i--)q1.push(make_pair(a[i],1));//1 ll x,x1,x2,x3; for(int i=1;i<=m;i++) { x1=0; x2=0; x3=0; if(q1.size()) x1=q1.front().first+q*(i-q1.front().second); if(q2.size()) x2=q2.front().first+q*(i-q2.front().second); if(q3.size()) x3=q3.front().first+q*(i-q3.front().second); if(q1.size() && (!q2.size()||x1>=x2) && (!q3.size()||x1>=x3)) x=x1,q1.pop();//= else if(q2.size() && (!q1.size()||x2>=x1) && (!q3.size()||x2>=x3)) x=x2,q2.pop();//else else if(q3.size() && (!q1.size()||x3>=x1) && (!q2.size()||x3>=x2)) x=x3,q3.pop(); if(i%t==0)printf("%lld ",x); q2.push(make_pair(x*u/v,i+1)); q3.push(make_pair(x-x*u/v,i+1));//i+1 } printf("\n"); for(int i=1;i<=n+m;i++) { x1=0; x2=0; x3=0; if(q1.size()) x1=q1.front().first+q*(m+1-q1.front().second); if(q2.size()) x2=q2.front().first+q*(m+1-q2.front().second); if(q3.size()) x3=q3.front().first+q*(m+1-q3.front().second); if(q1.size() && (!q2.size()||x1>=x2) && (!q3.size()||x1>=x3)) x=x1,q1.pop(); else if(q2.size() && (!q1.size()||x2>=x1) && (!q3.size()||x2>=x3)) x=x2,q2.pop(); else if(q3.size() && (!q1.size()||x3>=x1) && (!q2.size()||x3>=x2)) x=x3,q3.pop(); if(i%t==0)printf("%lld ",x); } return 0; }