2023牛客寒假算法基础集训营2 题解

前几天做了忘了写题解了..


A.Tokitsukaze and a+b=n (easy)

题面

第一题当时用的尺取法,有点笨.

AC代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define lowbit(x) ((x)&-(x))
int main() {
ios::sync_with_stdio(false);
int T;
cin>>T;
while(T--)
{
int n;
cin>>n;
int L1,R1,L2,R2;
cin>>L1>>R1;
cin>>L2>>R2;
int t=min(R2,n-L1);
int ans=0;
for(int i=L1;i<=R1;i++)
{
while(t+i>n)
t--;
if(t<L2)
break;
if(t+i==n)
ans++;
}
cout<<ans<<'\n';
}
return 0;
}


B. Tokitsukaze and a+b=n (medium)

题面

只需要计算 |[L1,R1]∩[L2,R2]|

AC原代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define lowbit(x) ((x)&-(x))
int main() {
ios::sync_with_stdio(false);
int T;
cin>>T;
while(T--)
{
int n;
cin>>n;
int L1,R1,L2,R2;
cin>>L1>>R1;
cin>>L2>>R2;
int L=n-R1,R=n-L1;
if(L<L2)
{
if(R<L2)
cout<<0<<'\n';
else if(R>=L2&&R<=R2)
cout<<R-L2+1<<'\n';
else
cout<<R2-L2+1<<'\n';
}
else if(L>=L2&&L<=R2)
{
if(R<=R2)
cout<<R-L+1<<'\n';
else
cout<<R2-L+1<<'\n';
}
else
{
cout<<0<<'\n';
}
}
return 0;
}

但其实求区间交集模的步骤可以简化.

|[L1,R1]∩[L2,R2]|= max(0,min(R1,R2)-max(L1,L2)+1)

改进后的AC代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define lowbit(x) ((x)&-(x))
int main() {
ios::sync_with_stdio(false);
int T;
cin>>T;
while(T--)
{
int n;
cin>>n;
int L1,R1,L2,R2;
cin>>L1>>R1>>L2>>R2;
int L=n-R2,R=n-L2;
cout<<max(0,min(R1,R)-max(L1,L)+1)<<'\n';
}
return 0;
}


D. Tokitsukaze and Energy Tree

题面

设 hi 为节点 i 的深度,则总能量为 ,由排序不等式,两数列 vi, hi 同序的时候 E 最大.

只需要算一下各个点的深度.

AC代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define lowbit(x) ((x)&-(x))
const int N=2e5+5;
struct node
{
int id;
int fa;
int ener;
}tree[N];
int v[N];
int dep[N];
int n;
void init()
{
memset(dep,-1,sizeof(dep));
dep[1]=1;
dep[0]=0;
for(int i=1;i<=n;i++)
{
int x=i;
if(tree[x].fa!=0)
{
x=tree[x].fa;
if(dep[x]!=-1)
dep[i]=dep[x]+1;
}
}
}
int main() {
ios::sync_with_stdio(false);
cin>>n;
int f;
tree[1].id=1,tree[1].fa=0,tree[1].ener=0;
for(int i=2;i<=n;i++)
{
cin>>f;
tree[i].fa=f;
tree[i].id=i;
tree[i].ener=0;
}
init();
for(int i=1;i<=n;i++)
cin>>v[i];
sort(v+1,v+1+n);
sort(dep+1,dep+1+n);
ll ans=0;
for(int i=1;i<=n;i++)
{
ans+=dep[i]*v[i];
}
cout<<ans<<'\n';
return 0;
}


J. Tokitsukaze and Sum of MxAb

题面

MxAb(i,j) = max(|ai−aj|,|ai+aj|) .

要求的是 .

可以看出 MxAb(i,j) 的值与 ai, aj 的符号无关,所以不妨 ai 全不负.

那么 MxAb(i,j) 就变成了 ai + aj .

则

AC代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define lowbit(x) ((x)&-(x))
const int N=1e5+5;
int main() {
ios::sync_with_stdio(false);
int T;
cin>>T;
while(T--)
{
int n;
cin>>n;
ll sum=0;
int a;
for(int i=1;i<=n;i++)
{
cin>>a;
if(a<0)
a=-a;
sum+=a;
}
sum*=2*n;
cout<<sum<<'\n';
}
return 0;
}


img_show