Codeforces Round 898 (Div. 4)

A. Short Sort

题目链接

题意

有三张带有字母 a 、 b 、 c 的卡片按某种顺序排成一行。您可以执行以下操作最多一次

-选两张牌,然后交换

操作后行是否可能变为 abc ?如果可能,则输出“Yes”,否则输出“No”。

分析

只要有一个字母的位置是正确的就可以变成abc

代码

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
//#include<queue>
//#include<map>
//#include<vector>
//#include<set>
//#include<deque>
//#include<bitset>
//#include<functional>

#define ll long long
#define inf 0x3f3f3f3f
using namespace std;

typedef pair<int,int>PII;

	
	
int main()
{
	int t;cin>>t;
	while(t--)
	{
		string s;
		cin>>s;
		if(s[0]=='a' || s[1]=='b' || s[2]=='c') puts("Yes");
		else puts("No");
	}
	
	
	return 0;
}

B. Good Kid

题目链接

题意

给定n个元素的数组a,现在可以将其中一个元素值加1,求操作完之后最大的元素之积

分析

给最小的元素加1即可

代码

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
//#include<queue>
//#include<map>
#include<vector>
//#include<set>
//#include<deque>
//#include<bitset>
//#include<functional>

#define ll long long
#define inf 0x3f3f3f3f
using namespace std;

typedef pair<int,int>PII;
const int N=15;

	
	
int main()
{
	int t;cin>>t;
	while(t--)
	{
		int n;cin>>n;
		int f[N];
		ll ans=1;
		for(int i=1;i<=n;i++) cin>>f[i];
		sort(f+1,f+n+1);
		f[1]++;
		for(int i=1;i<=n;i++) ans*=f[i];
		cout<<ans<<endl;
	}
	
	
	return 0;
}

C. Target Practice

题目链接

题意

给定一个10 x 10的靶子,如图最外圈得1分,最内圈得5分,击中用"x"表示,计算最终得分

分析

第一种方法直接打出得分表

第二种方法对于出现x的单元格,其分数值一定是行号,列号,11-行号,11-列号的最小值

代码

1.丑陋的打表

 

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
//#include<queue>
//#include<map>
//#include<vector>
//#include<set>
//#include<deque>
//#include<bitset>
//#include<functional>

#define ll long long
#define inf 0x3f3f3f3f
using namespace std;

typedef pair<int,int>PII;
int score[10][10]=
{1,1,1,1,1,1,1,1,1,1,
1,2,2,2,2,2,2,2,2,1,
1,2,3,3,3,3,3,3,2,1,
1,2,3,4,4,4,4,3,2,1,
1,2,3,4,5,5,4,3,2,1,
1,2,3,4,5,5,4,3,2,1,
1,2,3,4,4,4,4,3,2,1,
1,2,3,3,3,3,3,3,2,1,
1,2,2,2,2,2,2,2,2,1,
1,1,1,1,1,1,1,1,1,1};
char map[11][11];
	
	
int main()
{
	int t;cin>>t;
	while(t--)
	{
		for(int i=1;i<=10;i++) scanf("%s",map[i]+1);
		ll ans=0;
		for(int i=1;i<=10;i++)
		{
			for(int j=1;j<=10;j++) 
			{
				if(map[i][j]=='X') ans+=score[i-1][j-1];
			}
		}
		cout<<ans<<endl;
	}
	
	
	return 0;
}

2.找规律

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
//#include<queue>
//#include<map>
//#include<vector>
//#include<set>
//#include<deque>
//#include<bitset>
//#include<functional>

#define ll long long
#define inf 0x3f3f3f3f
using namespace std;

typedef pair<int,int>PII;

const int N=15;	
char map[N][N];

int main()
{
	int t;cin>>t;
	while(t--)
	{
		for(int i=1;i<=10;i++) scanf("%s",map[i]+1);
		ll ans=0;
		for(int i=1;i<=10;i++)
		{
			for(int j=1;j<=10;j++)
			{
				if(map[i][j]=='X')
				{
					ans+=min({i,j,11-i,11-j});
				}
			}
		}
		cout<<ans<<endl;
	}
	
	
	
	return 0;
}

 D. 1D Eraser

题目链接

题意

您将得到一张长为 n个单元格的纸条 s。每个单元格不是黑色就是白色。在操作中,您可以取任意 k个连续的单元格,并将它们全部变成白色。B表示黑色,W表示白色

找出移除所有黑色单元所需的最小操作次数。

分析

只要在长度为k的区间内都可以一次染成白色,那么计算出有几个这样长度为k且包含黑色的区间即可

代码

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
//#include<queue>
//#include<map>
//#include<vector>
//#include<set>
//#include<deque>
//#include<bitset>
//#include<functional>

#define ll long long
#define inf 0x3f3f3f3f
using namespace std;

typedef pair<int,int>PII;

	
	
int main()
{
	int t;cin>>t;
	while(t--)
	{
		string s;
		int n,k;
		cin>>n>>k>>s;
		ll ans=0;
		for(int i=0;i<s.size();i++)
		{
			if(s[i]=='B')
			{
				ans++;
				i+=k-1;
			}
		}
		cout<<ans<<endl;
	}
	
	
	return 0;
}

E. Building an Aquarium

题目链接

题意

你喜欢鱼,这就是你决定建一个水族馆的原因。你有一块由 n 根柱子组成的珊瑚,其中第 i 根柱子有 ai个单位高。之后,您将在珊瑚周围建造一个水箱,如下所示:

-选择一个整数 ℎ≥1 -水箱的高度。

在水箱的两侧建造高度为 ℎ 的墙。-然后,将水箱注满水,使每列的高度为 ℎ ,

除非珊瑚高于 ℎ ,否则不应向此列添加水。例如,对于 a=[3,1,2,4,6,2,5] 和高度ℎ=4 ,您最终将使用总共 w=8单位的水。

您最多可以使用 x 个单位的水来装满水箱,但您希望尽可能建造最大的水箱。

您可以选择的 h 的最大值是多少?

分析

求最大值,且答案具有单调性,二分答案即可

代码

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
//#include<queue>
//#include<map>
//#include<vector>
//#include<set>
//#include<deque>
//#include<bitset>
//#include<functional>

#define ll long long
#define inf 0x3f3f3f3f
using namespace std;

typedef pair<int,int>PII;
const int N=2e5+10;
ll f[N];
int n,m;

bool check(ll x)
{
	ll ans=0;
	for(ll i=1;i<=n;i++)
	{
		ans+=max(0ll,x-f[i]);
		if(ans>m) return false;
	}
	return true;
}
	
int main()
{
	int t;cin>>t;
	while(t--)
	{
		cin>>n>>m;
		for(int i=1;i<=n;i++) cin>>f[i];
		ll l=0,r=1e18;
		while(l+1<r)
		{
			ll mid=(l+r)>>1;
			if(check(mid)) l=mid;
			else r=mid;
		}
		if(check(l)) cout<<l<<endl;
		else cout<<r<<endl;
	}
	
	
	return 0;
}

F. Money Trees

题目链接

题意

现有n棵树,a数组为每棵树包含的果实数组,b数组为每棵树的高度数组,现给定一个数k,

现求一个区间,保证区间内的每个i都符合b[i]%b[i+1]==0并且该区间内的果实之和不大于k,输出该区间的最大长度

分析

用双指针维护区间记录最大值即可,其中果实之和可以用前缀和记录

代码

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
//#include<queue>
//#include<map>
//#include<vector>
//#include<set>
//#include<deque>
//#include<bitset>
//#include<functional>

#define ll long long
#define inf 0x3f3f3f3f
using namespace std;

typedef pair<int,int>PII;
const int N=2e5+10;
int a[N],b[N];
ll s[N];
	
	
int main()
{
	int t;cin>>t;
	while(t--)
	{
		int n,k;cin>>n>>k;
		for(int i=1;i<=n;i++)
		{
			cin>>a[i];
			s[i]=s[i-1]+a[i];
		}
		for(int i=1;i<=n;i++) cin>>b[i];
		ll ans=0;
		ll l=1,r=1;
		while(r<=n)
		{
			if(b[r-1]%b[r]) l=r;
			while(s[r]-s[l-1]>k) l++;
			ans=max(ans,r-l+1);
			r++;
		}
		cout<<ans<<endl;
	}
	
	
	return 0;
}

G. ABBC or BACB

题目链接

题意

给定一个只包含A,B的字符串s,每次可以执行下列操作的任意一种

1.将AB变为BC,获得一枚银币

2.将BA变为CB,获得一枚银币

求可能获得的最大银币

分析

对于字符串BAAAA,我们可以将BA变为CB,那么新串为CBAAA,直至变为CCCCB,那么获得的银币数恰好为4枚

对于字符串AAAAB,我们将AB变为BC,新串为AAABC,直至变为BCCCC,获得4枚银币

可以发现,每个B一定可以将一串连续的A全部变为银币,那么我们只需要计算出B的个数和连续的A的个数,选择将B个最长的连续A变为银币,此时银币数最多

代码

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
//#include<queue>
//#include<map>
//#include<vector>
//#include<set>
//#include<deque>
//#include<bitset>
//#include<functional>

#define ll long long
#define inf 0x3f3f3f3f
using namespace std;

typedef pair<int,int>PII;

	
	
int main()
{
	int t;cin>>t;
	while(t--)
	{
		string s;
		cin>>s;
		ll nb=0;
		for(int i=0;i<s.size();i++)
		{
			if(s[i]=='B') nb++;
		}
		vector<int>f;//每段连续a的个数
		for(int i=0;i<s.size();i++)
		{
			if(s[i]=='A')
			{
				int j=i;
				while(j<s.size() && s[j]=='A') j++;
				f.emplace_back(j-i);
				i=j-1;
			}
		}
		sort(f.begin(),f.end(),greater<>());
		ll ans=0;
		for(int i=0;i<f.size() && i<nb;i++) ans+=f[i];
		cout<<ans<<endl; 
	}
	
	
	return 0;
}

H. Mad City

题目链接

题意

给定一张n个点n条边的无向图,以及a和b的初始坐标,现在a想要抓到b,b非常聪明,可以预测到a的行动,两人同时开始行动,问a是否可以抓到b,如果抓不到,输出Yes,否则输出No

分析

首先n个点n条边的无向图,说明该图是一颗基环树。我们都知道树是n个点,n-1条边,基环树则在树的基础上多连接了一条边,这就导致它一定包含一个环。

引入了基环树之后,我们再来看,如果b想逃脱,那么他只能跑到环上和a不断地兜圈子,那么我们先找到环上的点是那些点,然后计算出a和b到这些点的最短距离,如果对于任意一个环上的点,a都能先一步比b到达,那么a一定能抓到b,反之只要有一个在环上点,b到这个点的距离比a小,那么b一定能逃脱

基环树:n个点n条边的连通图,一定包含一个环

找环:拓扑排序法,拓扑排序之后入度大于等于2的点即为环上的点

代码

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
//#include<map>
#include<vector>
//#include<set>
//#include<deque>
//#include<bitset>
//#include<functional>

#define ll long long
#define inf 0x3f3f3f3f
using namespace std;

typedef pair<int,int>PII;

const int N=2e5+10;
int de[N];//入度数组
vector<int>e[N];

int n,a,b;

void bfs(vector<int>&d,int x)//bfs求最短路
{
	fill(d.begin(),d.end(),-1);
	d[x]=0;
	queue<int>q;
	q.push(x);
	while(!q.empty())
	{
		auto t=q.front();
		q.pop();
		for(auto ed:e[t])
		{
			if(d[ed]==-1)
			{
				d[ed]=d[t]+1;
				q.push(ed);
			}
		}
	}
}
	
void top_sort()//拓扑排序
{
	queue<int>q;
	for(int i=1;i<=n;i++)
	{
		if(de[i]==1) q.push(i);
	}
	
	while(!q.empty())
	{
		auto t=q.front();
		q.pop();
		for(auto ed:e[t])
		{
			if(de[ed]>1)
			{
				de[ed]--;
				if(de[ed]==1) q.push(ed);
			}
		}
	}
}	
	
	
int main()
{
	int t;cin>>t;
	while(t--)
	{
		memset(de,0,sizeof de);
		cin>>n>>a>>b;
		for(int i=1;i<=n;i++)
		{
			int x,y;
			cin>>x>>y;
			e[x].emplace_back(y);
			e[y].emplace_back(x);
			de[x]++;
			de[y]++;
		}
		vector<int>da(n+1),db(n+1);//ab点到其他点的最短距离
		bfs(da,a);
		bfs(db,b);
		
		vector<int>circle;//环上点的集合
	    top_sort();
		for(int i=1;i<=n;i++)
		{
			if(de[i]>=2) circle.emplace_back(i);
		}
		//for(int i=0;i<circle.size();i++) cout<<circle[i]<<endl;
		int flag=0;
		for(int i=0;i<circle.size();i++)
		{
			if(da[circle[i]]>db[circle[i]])
			{
				flag=1;
		   	    break;
			}
		}
		
		if(flag) puts("YES");
		else puts("NO");
		for(int i=1;i<=n;i++) e[i].clear();
	}
	
	
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值