【noip2016】蚯蚓(单调性+队列)

题目贼长

大意是你有n个线段,每一秒你要拿出来最长的一个线段切成两段长度为[p*u](向下取整)和u-[p*u]两段(其中u是线段长,p是一个大于0小于1的实数)没被切的线段长度加q(0<q<200)。问m秒后的n+m条线段的长度(1n100000,1<=m<=7000000)

题解

乍一看是堆,可是堆被卡了。

我们建三个队列分别装最初的线段,和被切出来的两种线段。可以发现任何时候,一个队列里的线段长度单调递减,最长的线段,就从这三个队列里取出第一个比较就行。

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<cmath>
 5 #include<algorithm>
 6 using namespace std;
 7 const int N=10001000;
 8 long long n,m,q,u,v,t,z[N],qu1[N],qu2[N],qu3[N],h1,h2,h3,t1,t2,t3,cnt2[N],cnt3[N];
 9 bool cmp(long long x,long long y){
10     return x>y;
11 }
12 int main(){
13     scanf("%lld%lld%lld%lld%lld%lld",&n,&m,&q,&u,&v,&t);
14     for(long long i=1;i<=n;i++){
15         scanf("%lld",&z[i]);
16     }
17     sort(z+1,z+1+n,cmp);
18     for(long long i=1;i<=n;i++){
19         qu1[++t1]=z[i];
20     }
21     h1=h2=h3=1;
22     for(long long i=1;i<=m;i++){
23         long long a=qu1[h1]+(i-1)*q;
24         if(h1>t1)a=0;
25         long long b=qu2[h2]+(i-cnt2[h2]-1)*q;
26         if(h2>t2)b=0;
27         long long c=qu3[h3]+(i-cnt3[h3]-1)*q;
28         if(h3>t3)c=0;
29         long long d=max(a,max(b,c));
30         if(d==a)h1++;
31         else if(d==b)h2++;
32         else h3++;
33         long long e=(long long)d*u/v;
34         long long f=d-e;
35         qu2[++t2]=e;
36         qu3[++t3]=f;
37         cnt2[t2]=cnt3[t3]=i;
38         if(i%t==0)printf("%lld ",d);
39     }
40     printf("\n");
41     for(long long i=1;i<=m+n;i++){
42         long long a=qu1[h1]+m*q;
43         if(h1>t1)a=0;
44         long long b=qu2[h2]+(m-cnt2[h2])*q;
45         if(h2>t2)b=0;
46         long long c=qu3[h3]+(m-cnt3[h3])*q;
47         if(h3>t3)c=0;
48         long long d=max(a,max(b,c));
49         if(d==a)h1++;
50         else if(d==b)h2++;
51         else h3++;
52         if(i%t==0)printf("%lld ",d);
53     }
54     return 0;
55 }
View Code

 

posted @ 2018-07-22 17:31  Xu-daxia  阅读(187)  评论(0编辑  收藏  举报