Benelux Algorithm Programming Contest 2019

B. Breaking Branches

没人选一次会让n减一,所以n奇数先手必败,偶数先手必胜

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
const double PI= acos(-1.0);
const int M = 1e5+7;
/*
int head[M],cnt;
void init(){cnt=0,memset(head,0,sizeof(head));}
struct EDGE{int to,nxt,val;}ee[M*2];
void add(int x,int y){ee[++cnt].nxt=head[x],ee[cnt].to=y,head[x]=cnt;}
*/


int main()
{
	ios::sync_with_stdio(false);
  	cin.tie(0);
  	int n;
	  cin>>n;
	if(n%2==0)
	{
		cout<<"Alice"<<endl;
		cout<<1<<endl;
	 } 
	 else
	 {
	 	cout<<"Bob"<<endl;
	 }
	return 0;
}

J. Jazz it Up!

给n,让你找出m,m*n不是平方数的倍数。

找出n的质因子,m为不是n的质因子的质数。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
const double PI= acos(-1.0);
const int M = 1e5+7;
/*
int head[M],cnt;
void init(){cnt=0,memset(head,0,sizeof(head));}
struct EDGE{int to,nxt,val;}ee[M*2];
void add(int x,int y){ee[++cnt].nxt=head[x],ee[cnt].to=y,head[x]=cnt;}
*/

map<ll,ll>mp;
int vs[M];
int main()
{
	ios::sync_with_stdio(false);
  	cin.tie(0);
  	ll n;
	cin>>n;
	for(int i=2;i<=n;i++)if(n%i==0)mp[i]=1;
	for(int i=2;i<=n;i++)
	{
		if(vs[i])continue;
		for(int j=i+i;j<=n;j+=i)
			vs[j]=1;
	}
	for(int i=2;i<=n;i++)
	{
		if(vs[i]==0&&mp[i]==0)
		{
			cout<<i<<endl;
			return 0;
		}
	}
	return 0;
}

 H. Historic Exhibition

一个明显的贪心:底座直径相同,尽量用。

然后按底座最小的直径进行排序。

优先安排小的,因为后面的至少不会小与这个小的。

模拟下就行

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
const double PI= acos(-1.0);
const int M = 1e4+7;
/*
int head[M],cnt;
void init(){cnt=0,memset(head,0,sizeof(head));}
struct EDGE{int to,nxt,val;}ee[M*2];
void add(int x,int y){ee[++cnt].nxt=head[x],ee[cnt].to=y,head[x]=cnt;}
*/
struct node{
	int x,y,id;
}p[M];
int mp[M],a[M];
bool cmp(node a,node b)
{
	return a.x<b.x;
}
int main()
{
  	int n,m,x,y,sz=0,ct=0;
  	cin>>n>>m;
  	vector<int>v[M];
  	for(int i=1;i<=n;i++)
  	{
  		scanf("%d%d",&x,&y);
  		if(x>y)swap(x,y);
  		p[i]=node{x,y,i};
	}
	for(int i=1;i<=m;i++)scanf("%d",&a[i]),mp[a[i]]++;
	for(int i=1;i<=n;i++)
	{
		if(p[i].x==p[i].y)
		{
			x=p[i].x;
			if(mp[x])
			v[x].pb(i),mp[x]--,ct++;
		}
		else p[++sz]=p[i];
	}
	sort(p+1,p+1+sz,cmp);
	for(int i=1;i<=sz;i++)
	{
		x=p[i].x,y=p[i].y;
		if(mp[x])v[x].pb(p[i].id),mp[x]--,ct++;
		else
		{
			if(mp[y])
			v[y].pb(p[i].id),mp[y]--,ct++;
		}
	}
	bool f=true;
	if(ct==m&&m&&n)
	{
		for(int i=1;i<=m;i++)
		{
			int l=v[a[i]].size();
		//	cout<<a[i]<<"------------"<<l<<endl;
			printf("%d\n",v[a[i]][l-1]);
			v[a[i]].pop_back();
		}
	}
	else
	cout<<"impossible"<<endl;
	return 0;
}

 F. Find my Family

set维护下,前面的大于当前数的最小值,再看后面有没有大于这个值的数。

有就可以

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
const double PI= acos(-1.0);
const int M = 3e5+7;
/*
int head[M],cnt;
void init(){cnt=0,memset(head,0,sizeof(head));}
struct EDGE{int to,nxt,val;}ee[M*2];
void add(int x,int y){ee[++cnt].nxt=head[x],ee[cnt].to=y,head[x]=cnt;}
*/

int a[M],mx[M];
set<int>s;
int main()
{
	int K;
  	cin>>K;
  	vector<int>v;
  	for(int k=1;k<=K;k++)
  	{
  		int n;
  		cin>>n;
  		bool f=false;
  		s.clear();
  		for(int i=1;i<=n;i++)
  			scanf("%d",&a[i]);
  		mx[n+1]=0;
  		for(int i=n;i>=1;i--)mx[i]=max(a[i],mx[i+1]);
  		for(int i=1;i<=n;i++)
  		{
  			auto it=s.upper_bound(a[i]);
  		//	cout<<i<<" "<<*it<<"  "<<mx[i+1]<<endl;
  			if(it!=s.end()&&(*it<mx[i+1]))f=true;
  			s.insert(a[i]);
		}
		if(f)v.pb(k);
	}
	printf("%d\n",v.size());
	for(int i=0;i<v.size();i++)
	printf("%d\n",v[i]);
	return 0;
}

 E. Efficient Exchange

从高到低考虑每一位的钱数是直接付还是付大的然后找零钱。

dp保留最优即可

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
const double PI= acos(-1.0);
const int M = 1e5+7;
/*
int head[M],cnt;
void init(){cnt=0,memset(head,0,sizeof(head));}
struct EDGE{int to,nxt,val;}ee[M*2];
void add(int x,int y){ee[++cnt].nxt=head[x],ee[cnt].to=y,head[x]=cnt;}
*/

char s[M];
ll dp[M][2];//从前往后,第i位,正/倒  给钱  硬币最少是多少 
int main()
{
	scanf("%s",s+1);
  	int n=strlen(s+1),f;
  	memset(dp,0x3f,sizeof(dp));
  	dp[1][0]=s[1]-'0',dp[1][1]=10-(s[1]-'0')+1;
  	for(int i=2;i<=n;i++)
  	{
  		int tp=s[i]-'0';
  		int pr=s[i-1]-'0';
  	//	if(pr==0)f=-1;else f=1;
  		dp[i][0]=min(dp[i-1][0],dp[i-1][1])+tp;
  		dp[i][1]=min(dp[i-1][0]+1+(10-tp),dp[i-1][1]-1+(10-tp));
  	//	cout<<i<<" "<<dp[i][0]<<" "<<dp[i][1]<<endl;
	}
	cout<<min(dp[n][0],dp[n][1])<<endl;
	return 0;
}

A. Appeal to the Audience

长链剖分,每条链对应一个叶子节点,对应一个参赛者,排序求和即可

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
const double PI= acos(-1.0);
const int M = 3e5+7;

int head[M],cnt;
void init(){cnt=0,memset(head,-1,sizeof(head));}
struct EDGE{int to,nxt,val;}ee[M*2];
void add(int x,int y){ee[++cnt].nxt=head[x],ee[cnt].to=y,head[x]=cnt;}

int sz=0;
int n,m,x;
ll a[M],dep[M],du[M],son[M],b[M],nw,siz[M];
void dfs(int u,int fa)
{
	dep[u]=dep[fa]+1;
	int mx=-1;
	for(int i=head[u];i!=-1;i=ee[i].nxt)
	{
		int v=ee[i].to;
		if(v==fa)continue;
		dfs(v,u);
		siz[u]=max(siz[u],siz[v]+1);
		if(siz[v]>mx)mx=siz[v],son[u]=v;
	}
}
vector<ll>p;
void dfs2(int u,int fa)
{
	if(son[fa]!=u)
	{
		ll tp=u,z=0;
		while(tp!=-1)
		{
			tp=son[tp];
			z++;
		}
		if(u==0)z--;
		p.pb(z);
	}
	for(int i=head[u];~i;i=ee[i].nxt)
	{
		int v=ee[i].to;
		if(v==fa)continue;
		dfs2(v,u);
	}
}
int main()
{
  	cin>>n>>m;
  	init();memset(son,-1,sizeof(son));
  	for(int i=1;i<=m;i++)scanf("%lld",&a[i]);
  	for(int i=1;i<n;i++)scanf("%d",&x),add(x,i),add(i,x),du[i]++,du[x]++;
  	dfs(0,0);
  	sort(a+1,a+1+m);
  	nw=m+1;
  	ll ans=0;
  	dfs2(0,0);
  //	for(int i=0;i<n;i++)cout<<i<<" "<<son[i]<<endl;
  	sort(p.begin(),p.end());
  //	for(int i=0;i<p.size();i++)cout<<i<<" "<<p[i]<<endl;
  	for(int i=0;i<m;i++)ans+=a[i+1]*p[i];
	printf("%lld\n",ans);
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值