【NOIP2016】蚯蚓 --队列模拟
【NOIP2016】蚯蚓
话说去年这个题 我用priority_queue乱搞 结果惨不忍睹
q=0时送了50分 结果~~~~(>_<)~~~~
每次弹出最长的蚯蚓 把它切开 在放回队列
这个应该都能想到
只不过除了被切的蚯蚓 其他蚯蚓每秒都会增长
所以 我们可以用一个变量来记录增量
每次我们只弹出 队列元素最大值 把它加上增长变量 再去切它
并且保证队列里的元素都是减掉了增量的
注意 因为切得时候蚯蚓不会变长 所以放入队列的时候还要减去当前一秒增长的长度
这个题 数据比较大 所以用priority_queue会超时 我写priority_queue 只拿了75分
1 #include <cmath> 2 #include <queue> 3 #include <cstdio> 4 #include <cctype> 5 #include <algorithm> 6 7 const int MAXN=5*1e7+10; 8 9 int n,m,u,v,t,q,tag; 10 11 std::priority_queue<int> Q; 12 13 inline void read(int&x) { 14 int f=1;register char c=getchar(); 15 for(x=0;!isdigit(c);c=='-'&&(f=-1),c=getchar()); 16 for(;isdigit(c);x=x*10+c-48,c=getchar()); 17 x=x*f; 18 } 19 20 int hh() { 21 read(n);read(m);read(q); 22 read(u);read(v);read(t); 23 for(int x,i=1;i<=n;++i) read(x),Q.push(x); 24 double p=(double)u/v; 25 for(int i=1;i<=m;++i) { 26 int now=Q.top();Q.pop(); 27 int L1=floor(p*(now+tag)); 28 int L2=(now+tag)-L1; 29 Q.push(L1-tag-q); 30 Q.push(L2-tag-q); 31 if(i%t==0) printf("%d ",now+tag); 32 tag+=q; 33 } 34 printf("\n"); 35 for(int i=1;i<=n+m;++i) { 36 int L=Q.top();Q.pop(); 37 if(i%t==0) printf("%d ",L+tag); 38 } 39 printf("\n"); 40 return 0; 41 } 42 43 int sb=hh(); 44 int main(int argc,char**argv) {;}
正解是用三个队列模拟过程
一个队列存储原始蚯蚓 一个存储切了一半的蚯蚓 另一个存储另一半蚯蚓
每个蚯蚓在每一秒都会增长
当前蚯蚓被切以后 切成的两半分别都要小于对应队列的最小值
换句话说 后两个队列都是单调递减的
因为 我们每次取出当前最长的蚯蚓 加上累积的长度
切开之后 再减去累积的长度 在减去一个q放入队列与其他数保持同步 也就是这一秒他没有增长
可以看出整个操作没有加法操作 我们只是把一个蚯蚓切开后放入队列 这样显然 后切开的蚯蚓的长度小于之前切开的蚯蚓的长度
显然 队列是单调的
当前蚯蚓最大值从三个队列的队首取就好了
ps:不敢相信double了 在UOJ上被hack 就是double惹的祸
1 #include <cmath> 2 #include <cstdio> 3 #include <cctype> 4 #include <algorithm> 5 6 typedef long long LL; 7 const int INF=0x7fffffff; 8 const int MAXN=10000010; 9 10 int n,m,u,v,t,q,tag; 11 12 int t1,h1,t2,h2,h3,t3; 13 14 int q1[MAXN],q2[MAXN],q3[MAXN],q4[MAXN]; 15 16 inline void read(int&x) { 17 int f=1;register char c=getchar(); 18 for(x=0;!isdigit(c);c=='-'&&(f=-1),c=getchar()); 19 for(;isdigit(c);x=x*10+c-48,c=getchar()); 20 x=x*f; 21 } 22 23 inline bool cmp(int a,int b) {return a>b;} 24 25 inline int get() { 26 int N1=-INF,N2=-INF,N3=-INF; 27 if(h1<t1) N1=q1[h1]; 28 if(h2<t2) N2=q2[h2]; 29 if(h3<t3) N3=q3[h3]; 30 if(N1>=N2&&N1>=N3) {++h1;return N1;} 31 if(N2>=N1&&N2>=N3) {++h2;return N2;} 32 if(N3>=N2&&N3>=N1) {++h3;return N3;} 33 } 34 35 int hh() { 36 read(n);read(m);read(q);read(u);read(v);read(t); 37 for(int x,i=1;i<=n;++i) read(x),q1[t1++]=x; 38 std::sort(q1,q1+t1,cmp); 39 // double p=(double)u/v; 40 for(int i=1;i<=m;++i) { 41 int now=get(); 42 LL L1=(LL)u*(now+tag)/v; 43 LL L2=(LL)(now+tag)-L1; 44 q2[t2++]=L1-tag-q; 45 q3[t3++]=L2-tag-q; 46 if(i%t==0) printf("%d ",now+tag); 47 tag+=q; 48 } 49 printf("\n"); 50 for(int i=1;i<=n+m;++i) { 51 int now=get(); 52 if(i%t==0) printf("%d ",now+tag); 53 } 54 printf("\n"); 55 return 0; 56 } 57 58 int sb=hh(); 59 int main(int argc,char**argv) {;}
作者:乌鸦坐飞机
出处:http://www.cnblogs.com/whistle13326/
新的风暴已经出现
怎么能够停止不前
穿越时空 竭尽全力
我会来到你身边
微笑面对危险
梦想成真不会遥远
鼓起勇气 坚定向前
奇迹一定会出现