【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) {;}
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) {;}
队列模拟

 

posted @ 2017-09-23 20:00  拿叉插猹哈  阅读(176)  评论(0编辑  收藏  举报