考试总结 模拟26

心得:

T1比较水,set水过,之前的有个达哥的等比数列的题,考场上忘了那道题怎么做了,虽然也做出来了

T2思路很好想,但分数十分玄学,(不考虑细节+数据很水+代码很菜=50分玄学分数)

T3很显然的dp,看着像一个单调队列,但也不怎么会,线段树学习一下其他人的打法

 

题解

T1

一个贪心,对于每个数要尽量往前放,才能使块数更少,用一个set记录在当前块里的序列,若当前处理的数放入后会不符合要求,那就set清空,重新搞

T2

一个比较显然的图论题,对于取并集的情况,那就是这k个点向新点连边

取交集的话是从新点向这k个点连边,

但还要注意k==1时建双边,否则就会WA 0(理论上)

 1 //连有向边,<u,v>u信息在v中有,查询时就是看u能不能到v
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<cmath>
 6 #include<cstdlib>
 7 #include<set>
 8 #define R register
 9 using namespace std;
10 inline int read()
11 {
12     int f=1,x=0;char ch=getchar();
13     while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
14     while(ch<='9'&&ch>='0'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
15     return  x*f; 
16 }
17 const int maxn=1000000;
18 struct node{
19     int v,nxt;
20 }e[maxn*2];int h[maxn],nu;
21 void add(int x,int y)
22 {
23     e[++nu].v=y;
24     e[nu].nxt=h[x];
25     h[x]=nu;
26 }
27 int v[maxn];
28 int dfs(int nw,int to)//环???
29 {
30     v[nw]=1;
31     if(nw==to)return 1;
32     for(int i=h[nw];i;i=e[i].nxt)
33     {
34         int y=e[i].v;
35         if(v[y])continue;
36         if(dfs(y,to))return 1;
37     }
38     return 0;
39 }
40 int main()
41 {
42 //    freopen("data","r",stdin);
43     int tot=read(),m=read();
44     while(m--)
45     {
46         int opt=read();
47         if(opt)
48         {
49             int x=read(),y=read();
50             memset(v,0,sizeof v);
51             printf("%d
",dfs(x,y));
52         }
53         else 
54         {
55             int mot=read(),k=read();
56             tot++;
57             if(mot)
58             {
59                 for(int i=1;i<=k;++i)
60                 {
61                     int x=read();
62                     add(x,tot);
63                 }
64             }
65             else
66             {
67                 for(int i=1;i<=k;++i)
68                 {
69                     int x=read();
70                     add(tot,x);
71                 }
72             }
73         }
74     }
75 }
76 /*
77 g++ 2.cpp -o 2
78 ./2
79 
80 */
WA0

建完双边还要考虑dfs不能死循环,否则MLE60(dfs爆栈)

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<cstdlib>
 6 #include<set>
 7 #define R register
 8 using namespace std;
 9 inline int read()
10 {
11     int f=1,x=0;char ch=getchar();
12     while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
13     while(ch<='9'&&ch>='0'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
14     return  x*f; 
15 }
16 const int maxn=1000000;
17 struct node{
18     int v,nxt;
19 }e[maxn*2];int h[maxn],nu;
20 void add(int x,int y)
21 {
22     e[++nu].v=y;
23     e[nu].nxt=h[x];
24     h[x]=nu;
25 }
26 int dfs(int nw,int to)
27 {
28     if(nw==to)return 1;
29     for(int i=h[nw];i;i=e[i].nxt)
30     {
31         int y=e[i].v;
32         if(dfs(y,to))return 1;
33     }
34     return 0;
35 }
36 int main()
37 {
38 //    freopen("data","r",stdin);
39     int tot=read(),m=read();
40     while(m--)
41     {
42         int opt=read();
43         if(opt)
44         {
45             int x=read(),y=read();
46             printf("%d
",dfs(x,y));
47         }
48         else 
49         {
50             int mot=read(),k=read();
51             tot++;
52             if(mot)
53             {
54                 for(int i=1;i<=k;++i)
55                 {
56                     int x=read();
57                     add(x,tot);
58                     if(k==1)add(tot,x);
59                 }
60             }
61             else
62             {
63                 
64                 for(int i=1;i<=k;++i)
65                 {
66                     int x=read();
67                     add(tot,x);
68                     if(k==1)add(x,tot);
69                 }
70             }
71         }
72     }
73 }
74 /*
75 g++ 2.cpp -o 2
76 ./2
77 
78 */
MLE60

如果用vis数组标记且每次memset,TLE50

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<cstdlib>
 6 #include<set>
 7 #define R register
 8 using namespace std;
 9 inline int read()
10 {
11     int f=1,x=0;char ch=getchar();
12     while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
13     while(ch<='9'&&ch>='0'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
14     return  x*f; 
15 }
16 const int maxn=800000;
17 struct node{
18     int v,nxt;
19 }e[maxn];int h[maxn],nu;
20 void add(int x,int y)
21 {
22     e[++nu].v=y;
23     e[nu].nxt=h[x];
24     h[x]=nu;
25 }    
26 int v[maxn];
27 int dfs(int nw,int to)
28 {
29     v[nw]=1;
30     if(nw==to)return 1;
31     for(int i=h[nw];i;i=e[i].nxt)
32     {
33         int y=e[i].v;
34         if(v[y])continue;
35         if(dfs(y,to))return 1;
36     }
37     return 0;
38 }
39 int main()
40 {
41 //    freopen("data","r",stdin);
42     int tot=read(),m=read();
43     while(m--)
44     {
45         int opt=read();
46         if(opt)
47         {
48             int x=read(),y=read();
49             memset(v,0,sizeof v);
50             printf("%d
",dfs(x,y));
51         }
52         else 
53         {
54             int mot=read(),k=read();
55             tot++;
56             if(mot)
57             {
58                 for(int i=1;i<=k;++i)
59                 {
60                     int x=read();
61                     add(x,tot);
62                     if(k==1)add(tot,x);
63                 }
64             }
65             else
66             {
67                 
68                 for(int i=1;i<=k;++i)
69                 {
70                     int x=read();
71                     add(tot,x);
72                     if(k==1)add(x,tot);
73                 }
74             }
75         }
76     }
77 }
78 /*
79 g++ 2.cpp -o 2
80 ./2
81 
82 */
TLE50

然后就A了

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<cstdlib>
 6 #include<set>
 7 #define R register
 8 using namespace std;
 9 inline int read()
10 {
11     int f=1,x=0;char ch=getchar();
12     while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
13     while(ch<='9'&&ch>='0'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
14     return  x*f; 
15 }
16 const int maxn=800000;
17 struct node{
18     int v,nxt;
19 }e[maxn];int h[maxn],nu;
20 void add(int x,int y)
21 {
22     e[++nu].v=y;
23     e[nu].nxt=h[x];
24     h[x]=nu;
25 }
26 int dfs(int nw,int f,int to)
27 {
28     if(nw==to)return 1;
29     for(int i=h[nw];i;i=e[i].nxt)
30     {
31         int y=e[i].v;
32         if(y==f)continue;
33         if(dfs(y,nw,to))return 1;
34     }
35     return 0;
36 }
37 int main()
38 {
39 //    freopen("data","r",stdin);
40     int tot=read(),m=read();
41     while(m--)
42     {
43         int opt=read();
44         if(opt)
45         {
46             int x=read(),y=read();
47             printf("%d
",dfs(x,0,y));
48         }
49         else 
50         {
51             int mot=read(),k=read();
52             tot++;
53             if(mot)
54             {
55                 for(int i=1;i<=k;++i)
56                 {
57                     int x=read();
58                     add(x,tot);
59                     if(k==1)add(tot,x);
60                 }
61             }
62             else
63             {
64                 
65                 for(int i=1;i<=k;++i)
66                 {
67                     int x=read();
68                     add(tot,x);
69                     if(k==1)add(x,tot);
70                 }
71             }
72         }
73     }
74 }
75 /*
76 g++ 2.cpp -o 2
77 ./2
78 
79 */
Accept

 T3

很神奇的堆优化

$f[i]=min{f[j]+max(sum[i]-sum[j],b[j])}(i-k<=j<i)$

那么转移的时候只需要考虑当前$f[j]+b[j]$和$f[j]-sum[j]$(j不一定相同,但要符合范围)中的最小值,

所以分别存入堆中,第一个堆存f[j]+b[j],第二个存f[j]-sum[j],

找到当前合法两个队顶的元素x1,x2,f[i]=min{x1,x2+sum[i]}

那怎么处理对于每个j的max的问题?

对于每个点先放第一个堆,

在取第一个队顶元素的时候,若f[j]+b[j]<f[j]-sum[j]+sum[i],那就pop第一个堆,并放入第二个堆

然后就可以愉快地解决了,当然还要先往堆中放一个极大值

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<cstdlib>
 6 #include<set>
 7 #include<queue>
 8 #define INF 0x7ffffffffffffff
 9 #define ll long long
10 #define R register
11 using namespace std;
12 inline int read()
13 {
14     int f=1,x=0;char ch=getchar();
15     while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
16     while(ch<='9'&&ch>='0'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
17     return  x*f; 
18 }
19 const int maxn=500005;
20 inline ll min(ll x,ll y){return x<y?x:y;}
21 inline ll max(ll x,ll y){return x<y?y:x;}
22 int n,k;
23 int a[maxn],b[maxn],sum[maxn];ll f[maxn];
24 struct node{
25     ll da;
26     int id;
27     bool friend operator < (node x,node y){
28         return x.da>y.da;
29     }
30 };
31 priority_queue<node>q1;
32 priority_queue<node>q2;
33 int main()
34 {
35     n=read(),k=read();
36     for(R int i=1;i<=n;++i){
37         a[i]=read(),
38         sum[i]=sum[i-1]+a[i];
39         f[i]=INF;
40     }
41     for(R int i=0;i<n;++i)
42         b[i]=read();
43     f[0]=0;
44     node t;t.id=0,t.da=f[0]+b[0];
45     q1.push(t);    
46     t.da=INF,t.id=n+1;
47     q1.push(t);
48     q2.push(t);
49     for(R int i=1;i<=n;++i)
50     {
51         node t1=q1.top();
52         int j=t1.id;
53         while(q1.size()&&(j<i-k||t1.da<f[j]-sum[j]+sum[i])){
54             if(t1.da<f[j]-sum[j]+sum[i]){
55                 node t;t.id=j,t.da=f[j]-sum[j];
56                 q2.push(t);
57             }
58             q1.pop();
59             t1=q1.top();j=t1.id;
60         }
61         node t2=q2.top();
62         while(q1.size()&&t2.id<i-k)q2.pop(),t2=q2.top();
63         f[i]=min(t1.da,t2.da+sum[i]);
64         node t;t.da=f[i]+b[i],t.id=i;
65         q1.push(t);
66     }
67     printf("%lld
",f[n]);
68 }
View Code
愿你在迷茫时,记起自己的珍贵。
原文地址:https://www.cnblogs.com/casun547/p/11376351.html