CF1492

A.Three Swimmers

原题链接CF

题目大意:

给出T组数据,每组数据给出p,a,b,c,求最小的是a,b或c的倍数且大于等于p的数与p的差值。

解题思路:

直接做做完了。每次使p分别除以a,b,c(向上取整),取最小值再算差值即可。

小代码
#incIude <bits/stdc++.h>
#define int long long
using namespace std;
int T;
int a,b,c,p;

signed main()
{
	scanf("%lld",&T);
	while (T--)
	{
		scanf("%lld%lld%lld%lld",&p,&a,&b,&c);
		int ans=0x3f3f3f3f3f3f3f3f;
		ans=min(ans,(p+a-1)/a*a);
		ans=min(ans,(p+b-1)/b*b);
		ans=min(ans,(p+c-1)/c*c);
		printf("%lld\n",ans-p);
	}
	return 0;
}

B.Card Deck

原题链接

题目大意:

给出T组数据,每组数据给出栈中的n(1n1e5)个元素pi,每次操作可以取出栈顶若干元素,按原来顺序放入新的栈中,求最后使得新栈值最大的方案。我们定义栈的值为i=1nnnipi(默认栈顶为元素pn,栈底为元素p1)

解题思路:

这题简直就是反过来的出栈序列

容易想到贪心。越大的值越早到新栈里,新栈的值一定会越大。于是乎,我们定义一个前缀最大值数组,从后往前扫描,若出现旧的最大值了就输出当前的栈中所有元素(可结合代码理解)。

小?代码
#incIude <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+5;
int T;
int n;
int p[N];
stack <int> s;
int mx[N];

signed main()
{
	scanf("%lld",&T);
	while (T--)
	{
		scanf("%lld",&n);
		for (int i=1;i<=n;i++) 
		{
			scanf("%lld",&p[i]);
			mx[i]=max(mx[i-1],p[i]);//前缀最大值
		}
		for (int i=n;i>=1;i--)
		{
			s.push(i);
			while (!s.empty()&&mx[s.top()]>mx[i-1])//目前栈中存放的有好用的最大值
			{
				printf("%lld ",p[s.top()]);
				s.pop();
			}
		}
		printf("\n");
	}
	return 0;
}

C.Maximum width

原题链接

题目大意:

给出两个长度分别为n,m的字符串s1,s2(2mn2e5),保证s2s1的一个子串。要求找到s1的一个与s2相同的子串,使得该子串中相邻两个字符在s1中的距离最大,求这个最大值。

解题思路:

想让相邻两个字符距离最大,那么就是让相邻两个字符在可取到的范围里一个取最前面、一个取最后面,这样的距离最大。

于是乎,预处理出s2中每个字符可取到的最前、最后的位置,最后取最大的lsti+1fsti就是答案。

小代码
#incIude <bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+5;
int n,m;
string s1,s2;
int fst[N],lst[N];
int ans;

signed main()
{
	cin>>n>>m>>s1>>s2;
	s1=" "+s1,s2=" "+s2; 
	int j=0;
	for (int i=1;i<=m;i++)
	{
		while (s1[++j]!=s2[i]);
		fst[i]=j;
	}
	j=n+1;
	for (int i=m;i>=1;i--)
	{
		while (s1[--j]!=s2[i]);
		lst[i]=j;
	}
	for (int i=1;i<m;i++) ans=max(ans,lst[i+1]-fst[i]);
	cout<<ans;
	return 0;
}

D.Genius's Gambit

原题链接CF

题目大意:

给出三个整数a,b,k(0a,1b,ka+b2e5),要求构造出两个二进制形式的整数(x)2,(y)2,使得x,y都由a个"0",b个"1"组成,且(xy)2有k个"1",输出x,y的构造方案,若无法构造则输出"No"(不允许前导0的存在)

解题思路:

我们不妨构造出最大的x,然后考虑(xy)2有k个"1"的情况。当x,y相同数位的数不同时,x-y该数位就是1;若此次减法还向上借位,那么一直到上一个(x)2"1"、(y)2"0"的位置借位才会结束,在这个范围内x-y数位上都是1。

于是乎,我们可以在x上进行修改,找到l,r使得rl=k并且xl=1,xr=0,将xl改为0、xr改为1,这样修改过后的就是我们需要的y了。

挂分小技巧:漏掉无法构造成功的三种情况——a,b,k的边界问题。

不好看的代码
#incIude <bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+5;
int a,b,k;
int a1[N*2],a2[N*2];
int l,r;

signed main()
{
	cin>>a>>b>>k;
	if ((k+2>a+b&&k!=0)||(b==1&&k!=0)||(a==0&&k!=0))
	{
		cout<<"No";
		return 0;
	}
	l=2,r=l+k;
	for (int i=1;i<=b;i++) a1[i]=a2[i]=1;
	for (int i=b+1;i<=a+b;i++) a1[i]=a2[i]=0;
	if (k!=0)
	{
		while (r<=b) l++,r++;
		a2[l]=0,a2[r]=1;
	}
	cout<<"Yes"<<endl;
	for (int i=1;i<=a+b;i++) cout<<a1[i];
	cout<<endl;
	for (int i=1;i<=a+b;i++) cout<<a2[i];
	return 0;
}

E.Almost Fault-Tolerant Database

原题链接CF

题目大意:

给出n个长度为m的序列a,需构造一个序列s,使得对于任意序列,i=1m[aisi]2。输出构造方案,若无法构造则输出"No"。(nm2.5×105)

解题思路(口胡版):

我们不妨令s=a1,跑一遍,记录每个序列与s的最大差值Δ,若Δ2,那么直接输出s就行;若Δ>4,那么一定没有构造方案(可感性理解一下)。

那么现在就是Δ=3Δ=4的情况了。记差值与a1最大的序列为aid

Δ=3,考虑S={ansx,ansy,ansz},那么S中必然有一个元素与a1中的相同,有另一个元素与aid中的相同(这是显然的)。先令ansx=a1,xansy=aid,y,随后再使ansz=a1,z,向上述一样再次跑一遍,若aidans有三个不同,那么令ansz=aid,z再检查第二遍即可。若Δ>2,那么枚举下一种方案。共有6种方案,每种方案最多检查2遍,复杂度最多为 O(12nm)

Δ=4,这是好考虑的,S中必然有两个元素分别与a1aid中的元素相同。共有6种方案,枚举即可,复杂度最多为 O(6nm)

口胡完毕


posted @   还是沄沄沄  阅读(156)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
点击右上角即可分享
微信分享提示