2025牛客寒假算法基础集训营1

A

1
2
3
4
5
6
7
8
9
10
void solve(){
int n;cin>>n;
int ok=1;
while(n--){
int x;cin>>x;
if(x==1) ok=0;
}
if(ok) cout<<999999999999999989<<"\n";
else cout<<-1<<"\n";
}

B

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void solve(){
int n;cin>>n;
vector<vector<int>>g(n+1);
for(int i=0;i<n-1;i++){
int u,v;cin>>u>>v;
g[u].push_back(v);
g[v].push_back(u);
}
vector<int>ans;
for(int i=1;i<=n;i++){
if(g[i].size()==1){
ans.push_back(i);
}
}
if(ans.size()!=2){
cout<<-1<<"\n";
}else{
cout<<ans[0]<<" "<<ans[1]<<"\n";
}
}

C

D

1
2
3
4
5
6
7
8
9
10
11
12
void solve(){
int n;cin>>n;
map<int,int>mp;
int a=-1,b=-1;
for(int i=0;i<n;i++){
int x;cin>>x;
mp[x]++;
if(a==-1) a=x;
else if(b==-1&&x!=a) b=x;
}
cout<<((n%2==0&&mp.size()==2&&mp[a]==mp[b])?"Yes\n":"No\n");
}

E

好像挺典的,+1-1最小次数操作使得数组相等,就选中位数

所以选前半段中位数和后半段中位数,为了特判必须要为两个不同的数,在mid的基础上+-1

G

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
void solve(){
int n;cin>>n;
vector<int>a(n),p,need;
int sum=0;
map<int,int>mp;
for(int i=0;i<n;i++){
cin>>a[i];
sum+=a[i];
mp[a[i]]++;
if(a[i]<=0||a[i]>n){
p.push_back(a[i]);
}else if(a[i]>=1&&a[i]<=n&&mp[a[i]]==2){
mp[a[i]]--;
p.push_back(a[i]);
}
}
for(int i=1;i<=n;i++){
if(mp[i]==0){
need.push_back(i);
}
}
if(sum!=(n+1)*n/2){
cout<<-1<<"\n";
}else{
sort(p.begin(),p.end());
sort(need.begin(),need.end());
int mx=0;
for(int i=0;i<p.size();i++){
mx+=abs(p[i]-need[i]);
}
cout<<(mx+1)/2<<"\n";
}
}

H

对于[1,n]的每一个点i,都必须找到某个区间[l,r],其中l<=i<=r

如果有多个区间满足,贪心思想就是找到一个一定不会使得答案变差的方法

每次遍历到点i时,我们将所有<=i的左端点都入队,选取其中最小的右端点,这样一定不会使得答案变差

因为如果所有待选的r都不同,下一个点一定还有的选;若存在相同r,i<r下一个数还是有解,i==r此时产生空选项,无答案,无论哪一种情况都不会使得答案变差

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
void solve(){
int n;cin>>n;
vector<array<int,2>>a(n+1);
vector<vector<array<int,2>>>g(n+1);
for(int i=1;i<=n;i++){
cin>>a[i][0]>>a[i][1];
g[a[i][0]].push_back({a[i][1],i});
}
vector<int>p(n+1,0);
priority_queue<array<int,2>,vector<array<int,2>>,greater<array<int,2>>>pq;
for(int i=1;i<=n;i++){
for(auto [x,y]:g[i]){
pq.push({x,y});
}
if(pq.empty()||pq.top()[0]<i){
cout<<-1;
return;
}
p[pq.top()[1]]=i;
pq.pop();
}
for(int i=1;i<=n;i++){
cout<<p[i]<<" ";
}
}

J

A和任意数的gcd一定在A的因子中

$a_i{XOR}a_j=gcd(a_i,a_j)$,等价于$a_j=gcd(a_i,a_j)XORa_i$

我们枚举数组a,同时枚举a的所有因子,如果因子XOR$a_i$存在的话,等价于$a_j$存在

为了避免重复,我们要求$a_i>a_j$

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
void solve(){
int n;cin>>n;
vector<int>a(n);
map<int,int>mp;
for(int i=0;i<n;i++){
cin>>a[i];
mp[a[i]]++;
}
sort(a.begin(),a.end());
int ans=0;
for(int i=0;i<n;i++){
for(int j=1;j*j<=a[i];j++){
int x=j^a[i];
if(a[i]%j) continue;
if(x>a[i]&&gcd(x,a[i])==j) ans+=mp[x];
if(j*j!=a[i]){
x=(a[i]/j)^a[i];
if(x>a[i]&&gcd(x,a[i])==a[i]/j) ans+=mp[x];
}
}
}
cout<<ans;
}

M

Welcome to my other publishing channels