个人训练赛3

A - Kefa and Park
题意:Kefa要到公园里的餐厅吃饭,也就是图的叶子节点,但是Kefa害怕猫,猫的位置已经给出。其中猫**连续**出现的次数不超过m次,Kefa便可通过这条路,问Kefa能到几个餐厅吃饭。
分析:此题是典型的dfs,遍历所有点即可。(比赛的时候没读懂连续m,加上对dfs不太熟悉就没做出来。。。。)
代码如下:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
const int maxn=1e5+10;
bool vis[maxn];//标记出现猫的的点 
bool dis[maxn];//标记已经走过的的点 
vector<int> v[maxn];//存图 
int n,m;
int ans=0;
void dfs(int x,int y)
{
	int ant=0;
	if(vis[x]==1)
		y--;
	else
		y=m;
	dis[x]=1;
	for(int i=0;i<v[x].size();i++)
		if(dis[v[x][i]]==0)
			ant++;//ant为v[x][i]当前子节点数 
	if(y>=0&&ant==0)//当y>=0,且子节点数为0(说明该点为叶子节点),ans++; 
		ans++;
	else if(y>=0)
	{
		for(int i=0;i<v[x].size();i++)
		{
			if(dis[v[x][i]]==0)
				dfs(v[x][i],y);
		}
	}
}
int main()
{
	int a,b;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
		scanf("%d",&vis[i]);
	for(int i=0;i<n-1;i++)
	{
		scanf("%d%d",&a,&b);
		v[a].push_back(b);
		v[b].push_back(a);
	}
	dfs(1,m);
	printf("%d\n",ans);
	return 0;
 } 

D - Alex and a Rhombus  

 签到题,关系为a[i]=a[i-1]+(i-1)*4;

代码如下:

#include<cstdio>
#include<algorithm>
#include<string.h>
using namespace std;
int main()
{
	int a[105];
	int n; 
	a[1]=1;
	for(int i=2;i<=100;i++)
	{
		a[i]=a[i-1]+(i-1)*4;
	}
	scanf("%d",&n);
	printf("%d\n",a[n]);
	return 0;
}

E. Nick and Array

题意:给n个数,a[ 1..(n-1)..n],每个a[ i ]都可以进行ai:=−ai−1(0次,一次,或者多次操作),求变化后a[ i ]的乘积最大时,输出a[ i ],有多种答案,输出一种即可。

分析:这道题有一些贪心的思想,非负数进行该操作后绝对变大乘积的绝对值也变大。当n为偶数时(乘积为正数),可以将所有的正数进行该操作;当n为奇数时只需要有一个数为正数其他都为负数即可,易当进行该操作变成正数的值是所有a[ i ]中再大的时,那么就将这个数变成正数即可;

代码如下:

#include<cstdio>
#include<algorithm>
#include<string.h>
#include<cstring>
#include<map>
#include<cmath>
using namespace std;
const int maxn=1e5+10;
const int maxn2=1e6+10;
int main()
{
	int a[maxn];
	int n;
	int ans=0;
	int ant=0;
	int awm=0;
	int x=-1,y=-1;
	scanf("%d",&n);
	for(int i=0;i<n;i++)
	{
		scanf("%d",&a[i]);
//		printf("a[i] %d\n",a[i]);
		if(a[i]>=0&&a[i]>=y)
		{
			x=a[i];
			y=a[i];
		}
		else if(a[i]<=0&&-1*a[i]-1>=y)
		{
			x=a[i];
			y=-1*a[i]-1;
		}
//		printf("x %d\n",x);	
	} 
//	printf("x %d\n",x);
	if(n&1)
	{
		bool flag=0;
		for(int i=0;i<n;i++)
		{
			if(flag==0&&a[i]==x)
			{
				if(x<0)
					x=-1*x-1;
				printf("%d ",x);
				flag=1;
			}
			else if(a[i]>=0)
			{
				a[i]=-1*a[i]-1;
				printf("%d ",a[i]);
			}
			else 
				printf("%d ",a[i]);
		}
	}
	else
	{
		for(int i=0;i<n;i++)
		{
			if(a[i]>=0)
				a[i]=-1*a[i]-1;
			printf("%d ",a[i]);	
		}
	
	}
	printf("\n");
	return 0;
}
/*
5
-3 -2 -1 1 2
4 
0 0 0 0
5
-3 -1 1 2 3
5 
-7 4 3 -2 1 
*/

F - Valeriy and Deque  

(含题解)

 

G. Circle Metro

题意:a,b坐在两条不同的地铁线上

a 乘坐地铁路线为

1→2→…→n→1→2→…

b 乘坐地铁的路线为

n→(n−1)→…→1→n→(n−1)→…
已知 n a上车车站a,下车车站下,b上车车站b, 下车车站y。

问a,b是否同时待在一个车站(两人同时出站不算)

分析:模拟即可

代码如下:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
int main()
{
	int n;
	int a,x,b,y;
	bool flag=0;
	scanf("%d%d%d%d%d",&n,&a,&x,&b,&y);
	while(a!=x&&b!=y)
	{
		a=(a+1)%n;
		b=(b-1+n)%n;
		if(a==0)
			a=n;//取余无法达到n,当a==0时,即为第n站 
		if(b==0)
			b=n;//
		if(a==b&&!(a==x&&b==y))
		{
			flag=1;
			break;
		}
	}
	if(flag)
		printf("YES\n");
	else
		printf("NO\n");
	
	return 0;
}

H. Pairs

题意比较容易理解。

分析(自己写的比较复杂一点):首先结构体记录下每个点出现的次数和这个点,然后排序,从最大的开始遍历(剪枝)。记录过程中用map记录下每种情况的个数。

代码如下:

#include<cstdio>
#include<algorithm>
#include<string.h>
#include<cstring>
#include<map>
using namespace std;
typedef pair<int,int> pii;
const int maxn=300000+10;
map<pii,int>q;
int n,m;
struct node{
	int id=0;
	int sam=0;
}s[maxn];
bool cmp(node x,node y)
{
	return x.sam>y.sam;
}
int main()
{
	int x,y;
	pii rr,pp;
	bool flag=0;
	int ans=0;
	scanf("%d%d",&n,&m);
	for(int i=0;i<m;i++)
	{
		scanf("%d%d",&x,&y);
		s[x].id=x;
		s[y].id=y;
		s[x].sam++;
		s[y].sam++;
		rr.first=x,rr.second=y;
		q[rr]++;
	}
	sort(s,s+n+1,cmp);
	if(m&1)
		ans=m/2+1;
	else
		ans=m/2;
	for(int i=0;i<n;i++)
	{
		if(s[i].sam<ans)
			break; 
		for(int j=i+1;j<=n;j++)
		{
			if(s[j].sam<m-s[i].sam)
				break;
			rr.first=s[i].id,rr.second=s[j].id;
			pp.first=s[j].id,pp.second=s[i].id;
			if(s[i].sam+s[j].sam-q[rr]-q[pp]>=m)
			{
				flag=1;
				break;
			}
		}
		if(flag)
			break;
	}
	if(flag)
		printf("YES\n");
	else
		printf("NO\n");
	return 0;
}

G. Increasing by Modulo

 

题意:n个整数最大不超过m,问最少进行多少次操作能使数组非递减 

分析:操作的选择可用二分解决,l=0  r=m 

#include<cstdio>
#include<algorithm>
#include<string.h>
#include<cstring>
#include<map>
using namespace std;
const int maxn=300000+10;
int n,m;
int a[maxn];
int b[maxn];
bool abc(int x)
{
	b[1]=a[1];
	if(a[1]+x>=m)
		b[1]=0;
	for(int i=2;i<=n;i++)
	{
		if(a[i]>b[i-1])
		{
			b[i]=a[i];
			if(a[i]+x>=m&&(a[i]+x)%m>=b[i-1]) 
				b[i]=b[i-1];
		}
		else if(a[i]+x>=b[i-1])
			b[i]=b[i-1];
		else
			return false;
	}
	return true;
} 
int main()
{
	
	int mod;
	int ans;
	int l,r;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	r=m+1;
	l=0;
	while(l<=r)
	{
		mod=(l+r)/2;
		if(abc(mod))
		{
			ans=mod;
			r=mod-1;
		}
		else
			l=mod+1;
	}
	printf("%d\n",ans);
	return 0;
}

 

  

发布了40 篇原创文章 · 获赞 2 · 访问量 857

猜你喜欢

转载自blog.csdn.net/qq_43851311/article/details/103263731
今日推荐