1.22 排位赛

A:Not Shading

题目描述:

块染色问题

主要思路:

没啥思路,就是简单的分情况讨论。

B:Not Sitting

题目描述:

小红可以给座位涂色防止小明坐上去。
小明想离小红近一点,小红想离小明远一点,问当小红涂色0-n-2时小明和小红的距离为多少?

主要思路:

因为小红每次涂色都是最佳的策略,所以小红每次涂色的格子都是上一次小明占的位置。直接算一下每一个点到四个边的最大值然后排序输出即可。

#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
typedef long long ll;
char a[110][110];
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		vector<ll> ans;
		int n,m;
		cin>>n>>m;
		for(ll i=1;i<=n;i++)
		{
			for(ll j=1;j<=m;j++)
				ans.push_back(max(i-1,n-i)+max(j-1,m-j));
		}
		sort(ans.begin(),ans.end());
		for(int i=0;i<ans.size();i++) cout<<ans[i]<<' ';
		cout<<endl;
	}
	return 0;
}

C:Not Assigning

题目描述:

给定一棵树,让你给每一条边赋权满足每一条边以及任意两条相邻的边权值和都是素数。

主要思路:

因为除了2,所有的素数都是奇数,两个奇数的和一定是偶数,那么只能使用2和另一个+2仍为素数的素数和2交替出现,所以这棵树必须可以退化为一条链,否则无解。

#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<map>
using namespace std;
const int N=1e5+10;
typedef long long ll;
typedef pair<int,int> pa;
vector<int> a[N];
int ans[N];
map<pa,int> bookid;
struct node
{
	int id,x,y;
}edge[N];
void find(int x,int c)
{
	for(int i=0;i<a[x].size();i++)
	{
		int y=a[x][i];
		if(ans[bookid[{x,y}]]==0)
		{
			ans[bookid[{x,y}]]=c;
			if(c==2)
				find(y,3);
			else find(y,2);
		}
	}
}
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		memset(ans,0,sizeof(ans));
		int n;
		cin>>n;
		for(int i=1;i<n;i++)
		{
			int x,y;
			cin>>x>>y;
			edge[i].id=i,edge[i].x=x,edge[i].y=y;
			bookid[{x,y}]=i;
			bookid[{y,x}]=i;
			a[x].push_back(y);
			a[y].push_back(x);
		}
		//必须可以为一条链
		bool flag=0;
		for(int i=1;i<=n;i++)
		{
			if(a[i].size()>=3)
			{
				flag=1;
				break;
			}
		} 
		if(!flag)
		{
			ans[1]=2;
			find(edge[1].x,3);
			find(edge[1].y,3);
			for(int i=1;i<n;i++) cout<<ans[i]<<' ';
			cout<<endl;
		}
		else
			cout<<-1<<endl;
		for(int i=1;i<=n;i++) a[i].clear();
	}
	return 0;
}

D:Not Adding

题目描述:

给定一个序列,可以在该序列尾部加入序列中任意两个数字的最大公约数(序列中不存在该数字),问最大可以加入几个数字?

主要思路:

本题主要利用埃氏筛的思想
首先可以加进去的数一定在1-maxai之间,所以遍历这个范围内的数看看可不可以加进去。

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int N=1e6+10;
int a[N];
bool book[N];
int main()
{
	int n;
	cin>>n;
	int maxa=0;
	int ans=0;
	for(int i=1;i<=n;i++) cin>>a[i],book[a[i]]=1,maxa=max(maxa,a[i]);
	//利用埃氏筛的思想 
	for(int i=1;i<=maxa;i++)//想让i作为加进去的那个数 
	{
		if(book[i]) continue;//i已经存在了 
		int last=-1;
		for(int j=i+i;j<=maxa;j+=i)
		{
			if(!book[j]) continue;
			last= last==-1?j:__gcd(j,last);//保证可以找到两个gcd=i的数 
			if(last==i)
			{
				ans+=1;
				break;
			}
		}
	}
	cout<<ans<<endl;
	return 0;
}

E:Oops, It’s Yesterday Twice More

题目描述:

每个格子上边都站着一个企鹅,使用’UDLR’将企鹅全都赶到指定位置。

主要思路:

先将所有企鹅都赶到离指定位置最近的一角,然后就可以看作一个企鹅从一角走到指定位置。

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int main()
{
	int n,a,b;
	cin>>n>>b>>a;
	string ans="";
	if(a-1>n-a)
		for(int i=1;i<n;i++) ans+='R';
	else for(int i=1;i<n;i++) ans+='L';
	if(b-1>n-b) for(int i=1;i<n;i++) ans+='D';
	else for(int i=1;i<n;i++) ans+='U';
	if(a-1>n-a)
		for(int i=1;i<=n-a;i++) ans+='L';
	else for(int i=1;i<=a-1;i++) ans+='R';
	if(b-1>n-b) for(int i=1;i<=n-b;i++) ans+='U';
	else for(int i=1;i<=b-1;i++) ans+='D';
	cout<<ans<<endl;
	return 0;
}

F:Klee in Solitary Confinement

题目描述:

给定一个序列,你可以任意选l,r让这段闭区间内的数+k(仅可以操作1次或0次)
问可以得到的最大的众数数量。

主要思路:

首先,在输入序列的时候先将各个数字出现的次数统计出来,如果给定的k=0的话,直接输出最大数量即可。
否则就从1-n依次遍历,因为要想找到众数的最大数量,只需要找到一段+k=众数的数尽量多且这段区间内=众数的数尽量少即可。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<map>
using namespace std;
const int N=4e6+10,M=2e6;
int a[N]; 
int num[N];
int op[N];
int main()
{
	int n,k;
	scanf("%d%d",&n,&k);
	int ans=0;
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		num[a[i]+M]+=1;
		ans=max(ans,num[a[i]+M]); 
	}
	for(int i=1;i<=n;i++)
	{
		op[a[i]+M]-=1;//这个可以统计出来区间内开始=众数的数
		if(op[a[i]+M]<0) op[a[i]+M]=0;
		op[a[i]+k+M]+=1;
		ans=max(ans,num[a[i]+k+M]+op[a[i]+k+M]);
	}
	if(k==0) ans-=1;
	printf("%d\n",ans);
	return 0;
}

G:Windblume Festival

题目描述:

给定一个长度为 的数组,你每次可以选择两个相邻的位置(末位置认为其后为首位置,即数组构成了一个环)使其前
边位置的数字减去后边位置的数字并将后边的数字清除,知道最终整个数组只剩下一个数,问剩下的数最大为多少。

主要思路:

1、考虑当数组中所有数组都是正数时,如果想要获得尽可能大的数,应该进行的操作为令其最小的数一直向后减直
到遇到剩余两个数字时,那么此时已经构造除了一个正数和一个负数的情况,令正数减去负数即可,这个过程的答案
相当于令除了最小数外所有的数字加和后再减去最小数,容易发现不存在更优答案。
2、当数组中正负数都存在时,对于负数的操作可以像情况1最小数减去一个数后相同,对正数的操作和情况1相同。
容易发现最后的结果就是所有数的和。
3、当数组中仅存在负数时,容易发现其和情况1的差距仅在于第一次选择的数应该为最大的数,因为其绝对值贡献
值最小。
4、当n=1 时答案自然为输入值,需要特判。

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const int N=1e6+10;
ll a[N];
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		int n;
		scanf("%d",&n);
		ll ans=0;
		ll maxa=-1e12,mina=1e12;
		for(int i=1;i<=n;i++)
		{
			scanf("%lld",&a[i]);
			ans+=abs(a[i]);
			maxa=max(maxa,a[i]);
			mina=min(mina,a[i]);
		}
		if(n==1)
		{
			printf("%lld\n",mina);
			continue;
		}
		if(maxa<0) printf("%lld\n",ans+maxa*2);
		else if(mina>0) printf("%lld\n",ans-mina*2);
		else printf("%lld\n",ans);
	}
	return 0;
}
上一篇:vs2010下载Microsoft Visual Studio 2010 Express(vs2010中文版下载)速成官方合集正式版


下一篇:大盗阿福(线性DP)