Codeforces Round #583 (Div. 1 + Div. 2, based on Olympiad of Metropolises) A-E

RANK:1450      Rating:1728-26=1702

A:

枚举欧元 ,算美元  求最小值就行。

枚举是一个很重要的东西,一直在想O1的做法,想多了,浪费150分数。。

//KX
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
const int M = 1e5+7;
#define ls o*2
#define rs o*2+1
#define pb push_back
int main()
{
	ll n,d,e;
	cin>>n>>d>>e; 
	e=e*5;
	ll mi=n;
	for(int i=0;i<=n;i++)
	{
		if(i*d>n)break;
		mi=min(mi,(n-i*d)%e);
	}
	cout<<mi<<endl;
  	return 0;
}

B:直接算出boy最多多少个,girl最多多少个,然后算出共存的可能即可,吸取A题的教训,我直接枚举去算cnt,反正又不是我算。

//KX
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
const int M = 1e5+7;
#define ls o*2
#define rs o*2+1
#define pb push_back
int main()
{
	ll b,g,n;
	cin>>b>>g>>n;
	ll nb=min(n,b),ng=min(n,g);
	int cnt=0;
	for(int i=0;i<=nb;i++)
	{
		if(n-i<=ng)cnt++;
	}
	cout<<cnt<<endl;
  	return 0;
}

C:首先我们知道判断括号序列合不合法常用的方法是,从左到右枚举,ans初值等于0.遇到右括号-1,遇到左括号+1,判断中间是否出现负数,出现就不能。没出现且最后刚好等于0就一定合法。

这一题移动一个,不就相当于ans大于等于-1即可。

//KX
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
const int M = 2e5+7;
#define ls o*2
#define rs o*2+1
#define pb push_back
char s[M];
int main()
{
	int n;
	cin>>n;
	cin>>s;
	int cnt=0;
	bool flag=true;
	for(int i=0;i<n;i++)
	{
		if(s[i]==')')
		cnt--;
		else cnt++;
	//	printf("%d\n",cnt);
		if(cnt<-1)
		{
			flag=false;
			break;
		}
	}
	if(flag&&cnt==0)
	puts("Yes");
	else puts("No");
  	return 0;
}

D:题意没理解透,导致将近2小时做无用功。所以掉分了。。。

题目说只能往下和右走。。。我一直以为任意方向走,要根据连通性进行判断。

首先最多设置2个障碍物,堵住起点旁边那2个,然后如果起点终点不连通,则0个,否则枚举所有点当障碍物判起点终点是否联通。这个操作我想用带删除关系的并查集处理,但没做出来,不知道是不能还是我太弱了。。。希望有大神教教我/。

 

最后的时候我想到了dfs解法即正解。。。但是没敲完。。

其实这题很简单,只能往下右走,判设置最少障碍物能否到终点,即判是否至少有2条完全不同的路径到达终点,如果有,则要设置2个,如果只有一条,则设置1个,否则设置0个。

找路径直接能向下就向下,否则就向右,经过的点设成不可达点。跑2遍一定是尽可能不同的。

 

再说一下4个方向,如果4个方向这样做就错了,因为这种贪心正确的前提是必须贴着不可达的点走,2条路径尽可能背离,即第一条路径尽可能走最少的空间。所以如果4个方向,我们就判断怎样能贴着不可达点走2遍就行了。

//KX
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
const int M = 1e6+7;
#define ls o*2
#define rs o*2+1
#define pb push_back
vector<char>p[M];
vector<int>z[3];
char s[M];
int n,m;
bool to;
void dfs(int x,int y,int k)
{
	if(to)return;
//	printf("---------  %d  %d\n",x,y);
	if(x==n-1&&y==m-1)
	{
		to=true;
		return ;
	}
	if(x>=n||y>=m||x<0||y<0)return ;
	if(p[x][y]=='#')return ;
//	printf("%d %d   %c\n",x,y,p[x][y]);
	if(!(x==0&y==0))
	{
		p[x][y]='#';
		z[k].pb(x*m+y);
	}	
	dfs(x,y+1,k);
	dfs(x+1,y,k);
}
int mp[M];
int main()
{
/*	freopen("1.in","r",stdin);
	freopen("1.out","w",stdout);*/
	cin>>n>>m;
	for(int i=0;i<n;i++)
	{
		scanf("%s",s+1);
		int len=strlen(s+1);
		for(int j=1;j<=len;j++)
		{
			p[i].pb(s[j]);
		}
	}
	dfs(0,0,1);
	if(!to){
		puts("0");
		return 0;
	}
	to=false;
	dfs(0,0,2);
	if(!to){
		puts("1");
		return 0;
	}
	else
		puts("2");
  	return 0;
}

E:我感觉这一题真的简单,第二天补题的时候,看懂题意,想了5分钟就出来了,可能不是在比赛,思维放松。

我们先让奇数灯泡   互相连接。然后,从左往右枚举灯泡,放其对应的另一个灯泡即可,。

为了保证从左往右能放,我们需要事先按一对灯泡直接的距离从大到小排序。

这样一定保证另一个灯泡有位置放。

比如:

3

3 3 3

这组样例

我们先连接  1 - 3  -5

然后枚举灯泡,1,发现2跟他距离要是3 ,所以在5后面接上2,再往后发现3跟4的距离也是3,由于我们往右推进,长链距离-1,但是之前接上了一个灯泡,距离又加1 .

由于刚开始距离最大是n,而且是递非增的。如果距离和长链相同,那么长链长度不变,如果距离比长链小,那么长链长度-1.这样保证始终长链长度大于距离,即一定可以构造出解。

再回到刚才样例。

1-3-5-2-4-6

这样连接即可。

 

//KX
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
const int M = 1e6+7;
#define ls o*2
#define rs o*2+1
#define pb push_back
struct node
{
	int id,d;
}P[M];
bool cmp(node a,node b)
{
	return a.d>b.d;
}
int l[M],r[M];
int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&P[i].d);
		P[i].id=i*2-1;
	}
	sort(P+1,P+1+n,cmp);
	for(int i=1;i<n;i++)
	{
		l[i]=P[i].id,r[i]=P[i+1].id;
	}
	int pre=r[n-1];
	int cnt=n-1;
	int rt=n;
	for(int i=1;i<=n;i++)
	{
		int dnow=P[i].d;
		l[++cnt]=P[i+dnow-1].id;
		r[cnt]=P[i].id+1;
		if(i+dnow-1==rt)
		P[++rt].id=r[cnt];
	}
	for(int i=1;i<=cnt;i++)
	{
		printf("%d %d\n",l[i],r[i]);
	}
  	return 0;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值