NOIP 2016 蚯蚓
https://www.luogu.org/problem/P2827
NOIP 2016 D2T2
比较朴素的想法是开一个大根堆,每次取出堆顶元素,切开放回去;
问题在于怎么维护每次增长的q长度;
根据相对论 可以想到,拿出的蚯蚓不增长,其它蚯蚓增长,等价于拿出的蚯蚓变短;
那么我们只需要维护蚯蚓增长的长度SUM,每次取出蚯蚓时加上SUM+=q,切开后每段减去SUM,最后统计时再加上总的SUM就好了;
但这样复杂度还是太高;
考虑到每次拿出最长的,后切开的两段肯定比先切开的两段短;
所以本身就有单调性,不用堆维护也可以;
参考网上的题解,开三个数组,分别储存切前的A1,切的第一段A2,切的第二段A3,每次从三个数组中选出最长的,切成两段,放到A2,A3中就好啦哇;
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cmath> 5 #include<cstring> 6 using namespace std; 7 const int M=7000002; 8 int h0,h1,h2,n,m,res,cnt,num; 9 int t0,t1,t2,q,u,v,top,a1,a2,t,sum; 10 int cut1[M],cut2[M],cut0[M]; 11 double p; 12 int ans[M]; 13 bool cmp(int x,int y){ 14 return x>y; 15 } 16 int main(){ 17 scanf("%d%d%d%d%d%d",&n,&m,&q,&u,&v,&t); 18 p=(double)u/v; 19 for(int i=1;i<=n;i++) 20 scanf("%d",&cut0[i]); 21 sort(cut0+1,cut0+1+n,cmp); 22 t0=n;h1=h2=h0=1;t1=t2=0; 23 for(int i=1;i<=m;i++){ 24 if(h0>t0){if(cut1[h1]>cut2[h2])top=cut1[h1++];else top=cut2[h2++];} 25 else if(cut0[h0]>=cut1[h1]&&cut0[h0]>=cut2[h2])top=cut0[h0],++h0; 26 else if(cut1[h1]>=cut2[h2]&&cut0[h0]<=cut1[h1])top=cut1[h1],++h1; 27 else top=cut2[h2],++h2; 28 top+=sum; 29 a1=floor(p*(double)top); 30 a2=top-a1; 31 sum+=q; 32 a1-=sum; 33 a2-=sum; 34 cut1[++t1]=a1; 35 cut2[++t2]=a2; 36 if(i%t==0) printf("%d ",top); 37 } 38 39 printf(" \n"); 40 for(int i=h0;i<=t0;i++) ans[++num]=cut0[i]; 41 for(int i=h1;i<=t1;i++) ans[++num]=cut1[i]; 42 for(int i=h2;i<=t2;i++) ans[++num]=cut2[i]; 43 sort(ans+1,ans+1+num,cmp); 44 for(int i=1;i<=num;i++){ 45 if(i%t==0) printf("%d ",ans[i]+sum); 46 } 47 return 0; 48 }