CF 1886C

发布于:2024-03-01 ⋅ 阅读:(64) ⋅ 点赞:(0)
#include<bits/stdc++.h>

using namespace std;

void solve()
{
	string s;
	long long pos;
	cin>>s>>pos;
	pos--;
	
	vector<char> ans;
	int len=s.size();
	bool ok=false;
	if(pos<len)
		ok=true;
	
	s+='0';
	
	for(auto c:s)
	{
		while(!ok&&ans.size()>0&&ans.back()>c)
		{
			pos-=len;
			len--;
			ans.pop_back();
			
			if(pos<len)
				ok=true;
		}
		
		ans.push_back(c);
	}
	
	cout<<ans[pos];
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	
	int t;
	cin>>t;
	
	while(t--)
		solve();
	
	return 0;
}

模拟

差点道心破碎,这个题没看明白题意,以为是删除字典序最大的元素,样例确实符合,但是不是这个意思,题目的意思是使得被操作的字符串字典序比前面一个字符串小

解法挺多细节,首先是输入的时候,位置可能是很大,因为一个字符串的长度就是 1e6 ,所以位置最多就是 1e12

位置是从 1 开始计算,但是字符串是从 0 开始存,所以需要把输入的 pos 减去 1

用一个堆栈来存字符串

最优的策略是从字符串的左边找到两个相邻的元素,左边的元素大于右边的元素,把左边的大的元素删除,要是没有找到符合条件的元素,就把最后一个字符删除,因为删除最后一个字符之后,新的字符串相当于原来字符串的前缀,题目一开头就说了字典序小的两种情况,要么就是一个字符串是另一个字符串的前缀,要么就是两个字符串前面的元素相等,后面的元素小一些,其实就是字典序的字面意思

我们需要找到 pos 这个位置,需要一定的码力,或者说模拟能力

我们找的位置是在第一个字符串的话,就可以直接找到答案,否则的话,需要寻找该位置在整个最后的字符串的哪个位置

每一次都是寻找相邻的两个元素,假设左边的元素大于右边的元素,就删掉左边的元素,相当于进行了一次操作,更新所有的数值,最后假设找到了该位置,也就是 pos 在 len 的范围内,len 表示的是某一个字符串的长度,最开始等于第一个字符串的长度,随着循环不断进行,它表示的是第二个,第三个,第四个……字符串的长度

把最后一个元素删除,可以在字符串最后面添加一个比 a 更小的元素,就一定满足最后一个元素大于添加的元素,也就是一定可以找到相邻的两个元素,删除左边的元素

最后输出答案即可

还是算比较难的题

最难的可能是归纳出修改的操作是啥,修改的操作是要找到相邻的两个元素,左边的元素比右边的元素大,删除左边的元素,其他都只是一些代码细节

经验是慢慢看,不着急,速度不是靠着急练出来的,速度是靠专注和熟练度练出来的,所以练速度一定要慢

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到