牛客白月赛18【题解】

https://ac.nowcoder.com/acm/contest/1221#question

Forsaken喜欢数论【线性筛】

在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
const int N=1e7*3+10;
typedef unsigned long long int LL; 
LL prime[N],st[N],ans[N],n,cnt,sum;
void init(int n)
{
    
    
	for(int i=2;i<=n;i++)
	{
    
    
		if(!st[i]) prime[cnt++]=i,ans[i]=i,sum+=ans[i];
		for(int j=0;prime[j]<=n/i;j++)
		{
    
    
			st[i*prime[j]]=1;
			ans[i*prime[j]]=prime[j];
			sum+=ans[i*prime[j]];
			if(i%prime[j]==0) break;
		}
	}
}
int main(void)
{
    
    
	cin>>n;
	init(n);
	cout<<sum;
	return 0;
}

Forsaken给学生分组

在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
typedef long long int LL;
LL n,k,a[N];
int main(void)
{
    
    
	cin>>n>>k;
	for(int i=0;i<n;i++) cin>>a[i];
	sort(a,a+n);
	LL sum=0;
	for(int i=0;i<k;i++) sum+=a[n-1-i]-a[i];
	cout<<sum;
	return 0;
}

Forsaken喜欢正方形

在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
vector<PII>ve,temp;
int dx[4]={
    
    1,-1,0,0};
int dy[4]={
    
    0,0,1,-1};
int cnt=0;
double f(PII a,PII b)
{
    
    
	int x=a.first,y=a.second;
	int xx=b.first,yy=b.second;
	return sqrt((x-xx)*(x-xx)+(y-yy)*(y-yy));
}
bool check(vector<PII> a)
{
    
    
	set<double>st;
	sort(a.begin(),a.end());
	for(int i=0;i<4;i++)
		for(int j=i+1;j<4;j++)
		{
    
    
			if(i+j==3) continue;
			st.insert(f(a[i],a[j]));
		}
	return st.size()==1;
}
void solve()
{
    
    
	if(check(ve)) 
	{
    
    
		puts("wen");
		cnt++;
		return;
	}
	for(int i=0;i<ve.size();i++)
	{
    
    
		for(int j=0;j<4;j++)
		{
    
    
			temp=ve;
			temp[i].first=temp[i].first+dx[j];
			temp[i].second=temp[i].second+dy[j];
			if(check(temp))
			{
    
    
				puts("hai xing");
				cnt++;
				return;
			}
		}
	}
}
int main(void)
{
    
    
	for(int i=0;i<4;i++)
	{
    
    
		int x,y; cin>>x>>y;
		ve.push_back({
    
    x,y});
	}
	solve();
	if(!cnt) puts("wo jue de bu xing");
	return 0;
}

Forsaken的三维数点【树状数组+二分】

在这里插入图片描述

#include<bits/stdc++.h> 
using namespace std;
typedef long long int LL;
const int N=5*1e5+10;
LL tr[N],n;
int lowbit(int x){
    
    return x&(-x);}
void add(int x,int v)
{
    
    
	for(int i=x;i<N;i+=lowbit(i)) tr[i]+=v;
}
LL query(int x)
{
    
    
	LL sum=0;
	for(int i=x;i;i-=lowbit(i)) sum+=tr[i];
	return sum;
}
int main(void)
{
    
    
	cin>>n;
	while(n--)
	{
    
    
		int op; cin>>op;
		if(op==1)
		{
    
    
			LL x,y,z; cin>>x>>y>>z;
			int index=ceil(sqrt(x*x+y*y+z*z));
			add(index,1);
		}else
		{
    
    
			int k; cin>>k;
			int l=0,r=1e5*5,ans=-1;
			while(l<r)
			{
    
    
				int mid=l+r>>1;
				if(query(mid)>=k)
				{
    
    
					 ans=mid;
					 r=mid;
				}
				else l=mid+1;
			}
			cout<<ans<<endl;
		}
	}
	return 0; 
}

Forsaken喜欢独一无二的树【独一无二的最小生成树】

在这里插入图片描述

#include<bits/stdc++.h> 
using namespace std;
const int N=1e5*3+10;
typedef long long int LL;
int p[N],n,m;
struct node{
    
    int a,b,c;};
bool cmp(node a,node b){
    
    return a.c<b.c;}
vector<node>ve;
int find(int x)
{
    
    
	if(x!=p[x]) p[x]=find(p[x]);
	return p[x];
}
void kruskal()
{
    
    
	LL sum1=0,sum2=0;
	for(int i=1;i<=n;i++) p[i]=i;
	sort(ve.begin(),ve.end(),cmp);
	for(int i=0;i<ve.size();i++)
	{
    
    
		int t=i;
		while(t+1<ve.size()&&ve[t+1].c==ve[i].c) t++;//将这些相同的边都拿出来
		for(int j=i;j<=t;j++)
		{
    
    
			int a=ve[j].a,b=ve[j].b,c=ve[j].c;
			if(find(a)!=find(b)) sum1+=c;//如果是可以加上去的那么都加上
		}
		for(int j=i;j<=t;j++)
		{
    
    
			int a=ve[j].a,b=ve[j].b,c=ve[j].c;
			if(find(a)!=find(b)) sum2+=c,p[find(a)]=find(b);//构造的最小生成树
		}
		i=t;
	}
	cout<<sum1-sum2;//差值就是答案。
}
int main(void)
{
    
    
	cin>>n>>m;

	while(m--)
	{
    
    
		int a,b,c; cin>>a>>b>>c;
		ve.push_back({
    
    a,b,c});
	}
	kruskal();
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_46527915/article/details/124535644