【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) {;}
priority_queue

 

正解是用三个队列模拟过程 

一个队列存储原始蚯蚓 一个存储切了一半的蚯蚓 另一个存储另一半蚯蚓 

每个蚯蚓在每一秒都会增长 

当前蚯蚓被切以后 切成的两半分别都要小于对应队列的最小值

换句话说 后两个队列都是单调递减的 

因为 我们每次取出当前最长的蚯蚓 加上累积的长度 

切开之后 再减去累积的长度 在减去一个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) {;}
队列模拟

 

转载于:https://www.cnblogs.com/whistle13326/p/7582371.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值