【训练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;
}
posted @ 2024-04-28 16:00  pengge666  阅读(10)  评论(0编辑  收藏  举报