[NOIp2016提高组]蚯蚓
题目大意:
给你n个不同长度蚯蚓,每秒从里面取出最长的砍下u/v变成两只,又把剩下的加长q。
问你在m之前的t,2t,3t...的时间上,砍的蚯蚓长度,
以及m秒后剩下所有的蚯蚓长度。
思路:
很容易想到用一个堆来解决,然而这样时间复杂度是O((m+n)log(m+n))的,过不去。
所以复杂度得是线性的。
考虑把原来的堆改成三个单调队列。
每个蚯蚓切成两半总会有一个长的、一个短的。
我们有q1维护原来的蚯蚓,q2维护砍下来长的一截蚯蚓,q3维护砍下来短的一截蚯蚓。
不考虑蚯蚓的生长,我们只需要每次砍完蚯蚓扔进去就可以了。
算长度只要把每个单位时间内增加的长度乘以时间加到蚯蚓上面就可以了。
注意中间结果开long long,不然只有70分。
1 #include<queue> 2 #include<cstdio> 3 #include<cctype> 4 #include<algorithm> 5 #include<functional> 6 typedef long long int64; 7 inline int getint() { 8 register char ch; 9 while(!isdigit(ch=getchar())); 10 register int x=ch^'0'; 11 while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); 12 return x; 13 } 14 const int N=100000; 15 int a[N]; 16 std::queue<int> q1,q2,q3; 17 inline int getmax() { 18 if(q1.empty()&&q2.empty()) { 19 const int ret=q3.front(); 20 q3.pop(); 21 return ret; 22 } 23 if(q1.empty()&&q3.empty()) { 24 const int ret=q2.front(); 25 q2.pop(); 26 return ret; 27 } 28 if(q2.empty()&&q3.empty()) { 29 const int ret=q1.front(); 30 q1.pop(); 31 return ret; 32 } 33 if(q1.empty()) { 34 if(q2.front()>q3.front()) { 35 const int ret=q2.front(); 36 q2.pop(); 37 return ret; 38 } 39 const int ret=q3.front(); 40 q3.pop(); 41 return ret; 42 } 43 if(q2.empty()) { 44 if(q1.front()>q3.front()) { 45 const int ret=q1.front(); 46 q1.pop(); 47 return ret; 48 } 49 const int ret=q3.front(); 50 q3.pop(); 51 return ret; 52 } 53 if(q3.empty()) { 54 if(q1.front()>q2.front()) { 55 const int ret=q1.front(); 56 q1.pop(); 57 return ret; 58 } 59 const int ret=q2.front(); 60 q2.pop(); 61 return ret; 62 } 63 if(q1.front()>=q2.front()&&q1.front()>=q3.front()) { 64 const int ret=q1.front(); 65 q1.pop(); 66 return ret; 67 } 68 if(q2.front()>=q1.front()&&q2.front()>=q3.front()) { 69 const int ret=q2.front(); 70 q2.pop(); 71 return ret; 72 } 73 if(q3.front()>=q1.front()&&q3.front()>=q2.front()) { 74 const int ret=q3.front(); 75 q3.pop(); 76 return ret; 77 } 78 return 0; 79 } 80 int main() { 81 int n=getint(),m=getint(),q=getint(),u=getint(),v=getint(),t=getint(); 82 for(register int i=0;i<n;i++) { 83 a[i]=getint(); 84 } 85 std::sort(&a[0],&a[n],std::greater<int>()); 86 for(register int i=0;i<n;i++) { 87 q1.push(a[i]); 88 } 89 for(register int i=1;i<=m;i++) { 90 const int max=getmax()+q*(i-1); 91 if(!(i%t)) printf("%d ",max); 92 q2.push(std::max((int64)max*u/v-q*i,(int64)max-(int64)max*u/v-(int64)q*i)); 93 q3.push(std::min((int64)max*u/v-q*i,(int64)max-(int64)max*u/v-(int64)q*i)); 94 } 95 putchar('\n'); 96 for(register int i=1;!q1.empty()||!q2.empty()||!q3.empty();i++) { 97 const int max=getmax(); 98 if(!(i%t)) printf("%d ",max+q*m); 99 } 100 return 0; 101 }