Solved:5/6
Rank:74
比賽連結
A. Penchick and Modern Monument
給定一個不增序列,修改最少的數字使其不降。
全都修改為出現次數最多的數即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
void solve(){
int n;
cin>>n;
vector<int> a(n);
for(int& x:a)cin>>x;
int ans=1,len=1;
for(int i=1;i<n;++i){
if(a[i]==a[i-1])++len;
else len=1;
ans=max(ans,len);
}
cout<<n-ans<<'\n';
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);
int T;
cin>>T;
while(T--)solve();
}
B. Penchick and Satay Sticks
給定一個排列,只能交換位置和值都相鄰的數,問能否排成有序
注意到這種規則下每個數最多移動一個位置,因此如果存在 \(|a_i-i|>1\) 就直接無解。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
bool solve(){
int n;
cin>>n;
vector<int> a(n);
for(int& x:a)cin>>x,--x;
for(int i=0;i<n;++i)if(abs(a[i]-i)>1)return 0;
return 1;
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);
int T;
cin>>T;
while(T--)cout<<(solve()?"YES":"NO")<<'\n';
}
C. Penchick and BBQ Buns
給定 \(n\),構造一個正整數序列,使得出現過的數字都至少出現兩次,且任意兩個相同數字的距離均為平方數。
\(n\) 為偶數時,\(\{1,1,2,2,\dots,\frac n2,\frac n2\}\) 即滿足條件。
\(n\) 為奇數時,必然存在一個數出現至少三次。即 \(p_2-p_1,p_3-p_2,p_3-p_1\) 同時為完全平方數。滿足這個條件最小的一組數是 \(9,16,25\)。因此 \(n\leq 25\) 無解。
另一方面,\(n=27\) 時容易構造出 \(\{1,2,2,3,3,4,4,5,5,1,6,6,7,7,8,8,9,9,10,10,11,11,12,13,13,1,12\}\) 滿足條件。
因此 \(n\geq 27\) 均有解,後面和偶數一樣填數就行。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
void solve(){
int n;
cin>>n;
if(!(n&1)){
for(int i=1;i<=n/2;++i)cout<<i<<' '<<i<<' ';
cout<<'\n';
}
else{
if(n<27)cout<<"-1\n";
else{
cout<<"1 2 2 3 3 4 4 5 5 1 6 6 7 7 8 8 9 9 10 10 11 11 12 13 13 1 12 ";
for(int i=14;i*2+1<=n;++i)cout<<i<<' '<<i<<' ';
cout<<'\n';
}
}
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);
int T;
cin>>T;
while(T--)solve();
}
D. Penchick and Desert Rabbit
有 \(n\) 棵樹,從第 \(i\) 棵樹出發,每次可以跳到右邊更矮的樹或者左邊更高的樹。對所有起點,求能跳到的最高的樹。
每個點的答案一定是一個字首 max,且跳的過程會被擋住當且僅當存在某個 \(i\) 使得 \(\max_{j=1}^i a_i \leq \min_{j=i+1}^n a_n\)。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
void solve(){
int n;
cin>>n;
vector<int> a(n+1);
for(int i=1;i<=n;++i)cin>>a[i];
vector<int> mx(n+2),mn(n+2);
mx[0]=0,mn[n+1]=1e9;
for(int i=1;i<=n;++i)mx[i]=max(mx[i-1],a[i]);
for(int i=n;i>=1;--i)mn[i]=min(mn[i+1],a[i]);
for(int i=1,j=1;i<=n;++i){
if(mx[i]<=mn[i+1]){
while(j<=i)cout<<mx[i]<<' ',++j;
}
}
cout<<'\n';
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);
int T;
cin>>T;
while(T--)solve();
}
E. Penchick and Chloe's Trees
給一棵樹,已知這棵樹由一棵完全二叉樹縮點生成,求這棵完全二叉樹的最小深度。
樹形 dp,設 \(f_u\) 表示 \(u\) 的子樹縮點前的最小深度。
假設已知 \(u\) 的全體兒子的深度。考慮貪心,每次找到深度最小的兩棵子樹(設為 \(d\))合併成 \(d+1\) 的子樹。
這就是二進位制加法的過程。即 \(f_u = \lceil\log_2(\sum_v d_{v_i})\rceil\)。
暴力模擬二進位制加法即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+5;
int n,x,f[N];
vector<int> e[N];
int t[N];
void dfs(int u){
int mx=0,cnt=0;
for(int v:e[u])dfs(v);
vector<int> buc;
for(int v:e[u]){
int x=f[v];
if(!t[x])++cnt;
++t[x];
buc.push_back(x);
while(t[x]==2){
t[x]=0,--cnt;
if(!t[x+1])++cnt;
++t[++x],buc.push_back(x);
}
mx=max(mx,x);
}
for(int x:buc)t[x]=0;
f[u]=mx+(cnt>1)+(e[u].size()==1);
}
void solve(){
cin>>n;
for(int i=1;i<=n;++i)e[i].clear(),f[i]=0;
for(int i=2;i<=n;++i)cin>>x,e[x].push_back(i);
dfs(1);
cout<<f[1]<<'\n';
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);
int T;
cin>>T;
while(T--)solve();
}