2024牛客寒假算法基础集训营2
A Tokitsukaze and Bracelet
题意
根据所给信息,求出强化等级
思路
每个数字分别对应不同的权值,直接判断计数即可
代码
/*******************************
| Author: AlwaysBeShine
| Problem: Tokitsukaze and Bracelet
| Contest: NowCoder
| URL: https://ac.nowcoder.com/acm/contest/67742/A
| When: 2024-02-05 13:03:28
|
| Memory: 524288 MB
| Time: 2000 ms
*******************************/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
unordered_map<int,int>qh;
qh[32] = qh[31] = qh[30] = qh[29] = 0;
qh[34] = qh[36] = qh[38] = qh[40] = 1;
qh[45] = 2;
qh[100] = 0;
qh[150] = 1;
qh[200] = 2;
int n;
cin >> n;
for(int i = 0;i < n;i++){
int sum = 0;
int a,b,c;
cin >> a >> b >> c;
cout << qh[a] + qh[b] + qh[c] << endl;
}
return 0;
}
B Tokitsukaze and Cats
题意
有 n n n 只猫,想用最少的防猫片在矩形区域困住所有猫
思路
两只相邻格子的猫,可以在他们联通的那部分少放一片防猫片
即每次读入时判断与当前格子相邻的
4
4
4 个格子是否有猫,有则自减
代码
/*******************************
| Author: AlwaysBeShine
| Problem: Tokitsukaze and Cats
| Contest: NowCoder
| URL: https://ac.nowcoder.com/acm/contest/67742/B
| When: 2024-02-05 13:09:09
|
| Memory: 524288 MB
| Time: 2000 ms
*******************************/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
bool cat[303][303];
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
ll n,m,k,sum = 0;
cin >> n >> m >> k;
sum = 4*k;
for(int i = 1;i <= k;i++){
ll x,y;
cin >> x >> y;
cat[x][y] = true;
if(cat[x-1][y])sum--;
if(cat[x+1][y])sum--;
if(cat[x][y-1])sum--;
if(cat[x][y+1])sum--;
}
cout << sum << endl;
return 0;
}
E Tokitsukaze and Eliminate (easy)
题意
有 n n n 种颜色的宝石,排成一列,每次可以取某颜色的最右侧的宝石,并消除自身以及自身右侧所有其他颜色的宝石,问至少多少次可以把所有宝石都消除
思路
用 set 存储剩余的颜色,每个颜色对应一个 大根堆 ,堆顶元素代表着对应颜色最右侧的宝石的位置,每次取堆顶元素时都要检查当前元素是否合法(是否该位置的宝石已经在之前的操作过程中被清除),不合法则弹出。
如果某一个颜色对应的堆顶已空,则从 set 容器中将对应颜色删除,直至 set 容器为空,即为删除完毕。
代码
/*******************************
| Author: AlwaysBeShine
| Problem: Tokitsukaze and Eliminate (hard)
| Contest: NowCoder
| URL: https://ac.nowcoder.com/acm/contest/67742/F
| When: 2024-02-05 18:42:02
|
| Memory: 524288 MB
| Time: 2000 ms
*******************************/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
void solve(){
int n,ans = 0;
cin >> n;
set<int>col;
vector<priority_queue<int>>pos(n+1);
for(int i = 1;i <= n;i++){
int temp;
cin >> temp;
col.emplace(temp);
pos[temp].emplace(i);
}
while(!col.empty()){
auto tps = col;
ans++;
int now = 999999999;
for(auto c:col){
now = min(now,pos[c].top());
}
for(auto c:col){
while(!pos[c].empty() && pos[c].top() >= now){
pos[c].pop();
}
if(pos[c].empty())tps.erase(c);
}
col = tps;
}
cout << ans << endl;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T;
cin >> T;
while(T--){
solve();
}
return 0;
}
F Tokitsukaze and Eliminate (hard)
题意
同上题
思路
同上题
代码
同上题
I Tokitsukaze and Short Path (plus)
题意
有一张 n n n 个顶点的完全图 G G G, 顶点编号是 1 1 1 到 n n n,编号为 i i i 的顶点的值是 a i a_i ai。
完全图指的是每对顶点之间都恰好有一条无向边的图。
对于顶点
u
u
u 和顶点
v
v
v 之间的无向边,边权计算方式如下:
w
u
,
v
=
{
0
,
u
=
v
∣
a
u
+
a
v
∣
+
∣
a
u
−
a
v
∣
,
u
≠
v
w_{u,v}=\begin{cases} 0, & u = v \\ |a_u+a_v|+|a_u-a_v|, & u \ne v \end{cases}
wu,v={0,∣au+av∣+∣au−av∣,u=vu=v
定义 d i s t ( i , j ) dist(i,j) dist(i,j) 表示顶点 i i i 为起点,顶点 j j j 为终点的最短路。求 ∑ i = 1 n ∑ j = 1 n d i s t ( i , j ) \sum_{i=1}^n \sum_{j=1}^n dist(i,j) ∑i=1n∑j=1ndist(i,j)
关于最短路的定义:
定义一条从
s
s
s 到
t
t
t 的路径为若干条首尾相接的边形成的序列且该序列的第一条边的起点为
s
s
s,最后一条边的终点为
t
t
t。
特别的,当
s
=
t
s=t
s=t 时该序列可以为空。
定义一条从
s
s
s 到
t
t
t 的路径长度为该路径中边权的总和。
定义
s
s
s 到
t
t
t 的最短路为
s
s
s 到
t
t
t 所有路径长度中的最小值。
思路
由分析得,如果想得到路径最短,联通所有点的过程中,要更多的重复经过边权小的边,尽可能少的重复经过边权大的边。
通过手动展开式子可得,发现 由
n
n
n 个点组成的这一张图,若序号根据顶点的值
a
a
a 依次递增
可得
∑
i
=
1
n
∑
j
=
1
n
d
i
s
t
(
i
,
j
)
=
4
∑
i
=
1
n
(
i
−
1
)
∗
a
i
\sum_{i=1}^n \sum_{j=1}^n dist(i,j) = 4\sum_{i=1}^n (i-1)*a_i
∑i=1n∑j=1ndist(i,j)=4∑i=1n(i−1)∗ai
代码
/*******************************
| Author: AlwaysBeShine
| Problem: Tokitsukaze and Short Path (plus)
| Contest: NowCoder
| URL: https://ac.nowcoder.com/acm/contest/67742/I
| When: 2024-02-05 19:26:34
|
| Memory: 524288 MB
| Time: 2000 ms
*******************************/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
void solve(){
ll n,sum = 0;
cin >> n;
std::vector<ll> a(n+1);
for(int i = 1;i <= n;i++){
cin >> a[i];
}
sort(a.begin(),a.end());
for(int i = 1;i <= n;i++){
sum += a[i]*(i-1);
}
cout << 4 * sum << endl;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T;
cin >> T;
while(T--){
solve();
}
return 0;
}
J Tokitsukaze and Short Path (minus)
题意
和上题区别在于本题的定义有所更改
w u , v = { 0 , u = v ∣ a u + a v ∣ − ∣ a u − a v ∣ , u ≠ v w_{u,v}=\begin{cases} 0, & u = v \\ |a_u+a_v|-|a_u-a_v|, & u \ne v \end{cases} wu,v={0,∣au+av∣−∣au−av∣,u=vu=v
同求 ∑ i = 1 n ∑ j = 1 n d i s t ( i , j ) \sum_{i=1}^n \sum_{j=1}^n dist(i,j) ∑i=1n∑j=1ndist(i,j)
思路
分析过程同上题
对式子展开后的分析有所不同,如果 w i , j > w i , a + w a , j w_{i,j} \gt w_{i,a} + w_{a,j} wi,j>wi,a+wa,j,则,可知 i i i 结点通过绕到 a a a 结点再到 j j j 结点的路程小于,直接从 i i i 到 j j j 。
则可知,任何两点间的路径边权关系,都可以转换到是否要绕路经过 最小边权 所对应的点。
在上题基础上稍加调整即可。
代码
/*******************************
| Author: AlwaysBeShine
| Problem: Tokitsukaze and Short Path (minus)
| Contest: NowCoder
| URL: https://ac.nowcoder.com/acm/contest/67742/J
| When: 2024-02-05 19:36:09
|
| Memory: 524288 MB
| Time: 2000 ms
*******************************/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
void solve(){
ll n,sum = 0;
cin >> n;
std::vector<ll> a(n+1,0);
for(int i = 1;i <= n;i++){
cin >> a[i];
}
sort(a.begin(),a.end());
for(int i = 1;i <= n;i++){
if(a[i] > 2*a[1]){
sum += 2 * a[1]*(n-i);
}else{
sum += a[i]*(n-i);
}
}
cout << 4 * sum << endl;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T;
cin >> T;
while(T--){
solve();
}
return 0;
}