Codeforces Global Round 10 A~D

目录

A - Omkar and Password

B - Omkar and Infinity Clock

C - Omkar and Waterslide

D - Omkar and Bed Wars


A - Omkar and Password

 给一个序列,每次操作可以合并两个相邻但不相等的数,问最终能把序列的长度合并到最短是多少;

如果存在两个相邻的数不相等,那么就能把序列合并为长度为1,否则就是n

#include <bits/stdc++.h>
using namespace std;
const int N=2e5+7;
int a[N];
int main()
{
	int t;
	cin >>t;
	while(t--)
	{
		int n;
		cin >>n;
		int f=0;
		for(int i=1;i<=n;i++) cin >>a[i];
		for(int i=1;i<=n;i++) if(i>1&&a[i]!=a[i-1]){f=1;break;}
		if(f) puts("1");
		else printf("%d\n",n);
	}
}

B - Omkar and Infinity Clock

 规律题,看到k那么大,肯定有规律,模拟一组数据就能看出来了,循环周期为2,判断k的奇偶负即可;

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+7;
int a[N];
int main()
{
	int t;
	cin >>t;
	while(t--)
	{
		ll n ,k;
		cin >>n>>k;
		int maxx=-0x3f3f3f3f;
		for(int i=0;i<n;i++) cin >>a[i],maxx=max(a[i],maxx);
		int temp=-0x3f3f3f3f;
		for(int i=0;i<n;i++) a[i]=maxx-a[i],temp=max(a[i],temp);
		if(k&1) for(int i=0;i<n;i++) printf("%d%c",a[i],i==n-1?'\n':' ');
		else for(int i=0;i<n;i++) a[i]=temp-a[i],printf("%d%c",a[i],i==n-1?'\n':' ');
	}
}

C - Omkar and Waterslide

 思路就是 序列中的每一个凹点都要变成和他距离最近的凸点一样高,并且凹点要在凸点的右侧,相当于存在  a[i] <a[i-1] 的话,加上两者的差即可;

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+7;
int a[N];
int main()
{
	int t;
	cin >>t;
	while(t--)
	{
		int n;
		cin >>n;
		ll sum=0;
		for(int i=0;i<n;i++) cin >>a[i],sum+=i>0&&a[i]<a[i-1]?a[i-1]-a[i]:0;
		cout <<sum<<endl;
	}
}

D - Omkar and Bed Wars

是个假DP(当然网上有大佬用五维DP,也有可能正解就是DP,极其复杂。。) 

 想了一个思路,假设以下几种情况:

  • ......RRR......   需要操作1次
  • ......RRRR.....    1次
  • .....RRRRR.....   1次
  • ......RRRRRR.....    2次

也就是连续的片段需要操作的次数就是:    长度 / 3 

 所以,现预处理字符串的所有连续片段的长度并且记录,对于首部和尾部片段如果相同,可以叠加到尾部;然后计算即可;

(对于字符串全是一种字符的情况: RRRRRRRRRR或者LLLLLLLLL,那么答案是   1 + (len-1) / 3 );

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+7;

int a[N];
int main()
{
	int t;
	cin >>t;
	while(t--)
	{
		string s;
		int n;
		cin >>n;
		cin >>s;
		//cout <<s<<endl;
		int res=0,cnt=1;
		for(int i=1;i<n;i++)
		{
			if(s[i]==s[i-1]) cnt++;
			else
			{
				a[++res]=cnt;
				cnt=1;
			}
		}
		a[++res]=cnt;
		ll ans=0;
		if(res>1) 
		{
			if(s[0]==s[n-1]) a[res]+=a[1],a[1]=0;
			for(int j=1;j<=res;j++) ans+=a[j]/3;
		}
//		else ans+=a[1]>=3&&a[1]%3==2? a[1]/3+1:a[1]/3;
		else ans+=1+(a[1]-1)/3;
		cout <<ans<<endl;
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值