【训练2】2024.4.12 饿了么【最小生成树】
第一题-塔子哥的质数和合数
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 2e5+100;
int n,arr[N];
signed main(){
cin>>n;
set<int> s;
for(int i=1;i<=n;i++){
cin>>arr[i];
if(arr[i]==1) continue;
s.insert(arr[i]);
}
cout<<s.size();
return 0;
}
/*
1
*/
第二题-塔子哥的魔法题
这道二分卡了我一下,真的难泵,刚开始思路存在问题,想着在二分里面直接判断完,但是这样是不对的。
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e6+100;
const int MAXV = (1LL << 30) - 1; // 将MAXV的类型改为long long
struct str{
int num[33];
}sum[N];
int n,m,arr[N];
signed main(){
// memset(sum,0,sizeof(sum));
cin>>n>>m;
// 初始化 sum 数组
for (int i = 0; i <= n; i++) {
memset(sum[i].num, 0, sizeof(sum[i].num));
}
for(int i=1;i<=n;i++){
cin>>arr[i];
for(int j=0;j<31;j++){
if(arr[i]&(1<<j)){
sum[i].num[j]=sum[i-1].num[j]+1;
}else{
sum[i].num[j]=sum[i-1].num[j];
}
}
}
// for(int i=1;i<=n;i++){
// for(int j=0;j<31;j++){
// cout<<sum[i].num[j]<<" ";
// }
// cout<<endl;
// }
int ql,qr,k;
while(m--){
cin>>ql>>qr>>k;
if(k>MAXV){
cout<<"-1\n";
continue;
}
int l=ql,r=qr;
int pos=-1;
while(l<=r){
int mid=(l+r)/2;
// check
int flag=1;
int tmp=0;
for(int i=0;i<31;i++){
int num=sum[mid].num[i]-sum[ql-1].num[i];
if(num){
tmp=tmp|(1<<i);
}
}
if(tmp<k){
flag=0;
}
// pandaun
if(flag){
r=mid-1;
pos=mid;
}else{
l=mid+1;
}
}
if(pos==-1){
cout<<"-1\n";
continue;
}
int ans=pos;
for(int i=0;i<31;i++){
int tnum=sum[pos].num[i]-sum[ql-1].num[i];
if(k&(1<<i)){
if(!tnum){
ans=-1;
break;
}
}else{
if(tnum){
ans=-1;
break;
}
}
}
cout<<ans<<endl;
}
return 0;
}
/*
5 5
3 2 3 3 6
1 2 3
1 5 7
1 4 7
2 2 2
2 3 7
*/
第三题-塔子哥删边
这道题目看出最小生成树之后就比较好弄了,剩下就是边界的判断。
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 2e5+100;
int f[N];
int getf(int v){
if(v!=f[v]){
f[v]=getf(f[v]);
}
return f[v];
}
bool merge(int u,int v){
int t1=getf(u);
int t2=getf(v);
if(t1!=t2){
f[t1]=t2;
return true;
}
return false;
}
int n,m;
struct Node{
int u,v,w;
}st[N];
bool cmp(Node a,Node b){
return a.w<b.w;
}
signed main(){
cin>>n>>m;
for(int i=1;i<=n;i++) f[i]=i;
int tot=0;
for(int i=1;i<=m;i++){
cin>>st[i].u>>st[i].v>>st[i].w;
tot+=st[i].w;
}
// 排除掉
for(int i=1;i<=m;i++){
merge(st[i].u,st[i].v);
}
set<int> check;
for(int i=1;i<=n;i++){
check.insert(getf(i));
}
if(check.size()>2){
cout<<"-1"<<endl;
return 0;
}
for(int i=0;i<=n;i++) f[i]=i;
sort(st+1,st+1+m,cmp);
vector<int> p;
int sum=0;
for(int i=1;i<=m;i++){
if(merge(st[i].u,st[i].v)){
p.push_back(st[i].w);
sum+=st[i].w;
}
}
sort(p.begin(),p.end());
// cout<<tot<<" "<<sum<<" "<<p[p.size()-1]<<endl;
int ans=0;
if(check.size()==2){
ans=tot-sum;
}else{
ans=tot-sum+p[p.size()-1];
}
cout<<ans<<endl;
return 0;
}