Educational Codeforces Round 153 (Rated for Div. 2)补题

Not a Substring(Problem - A - Codeforces)

题目大意:给一个由括号组成长为n的字符串s,我们要找出一个长度为2*n的字符串a,使得a中的括号是配对的,同时s不是a的子串。

思路:很显然我们面对的情况有限,可以落到两个字符之间来看:
():这种没法处理,因为只要是配好对的括号,一定会出现这个结构

)(:如果出现这个结构,可以补成(())

剩下的情况那么就是左括号在右括号左边的,我们全部拆散即可。

#include
using namespace std;
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		string s;
		cin>>s;
		if(s=="()") printf("NO\n");
		else
		{
			printf("YES\n");
			int r=0,c=0;
			for(int i=0;i

 Fancy Coins(Problem - B - Codeforces)

题目大意:现在有价值为1的普通硬币a1个花式硬币无限个,价值为k的硬币a2个花式硬币无限个,要求恰好凑出m,问至少用多少个花式硬币。

思路:这题很容易想到dp,就先将两种普通硬币能凑出来的数统计出来,然后找一个最近的用花式硬币去补,但是很显然,这个最近的就有说法了,如果只用1枚价值k的硬币显然比用三枚价值1的花式硬币划算,但是后一种情况距m更近。但是我们很容易发现,这里求的是花式硬币的最小个数,那么很显然合法情况有很多,故而我们使用二分查找。check函数检查凑出m需要补多少个硬币,肯定优先补价值k的花式硬币,如果差值小于k之后再补价值为1的花式硬币,

#include
using namespace std;
int m,k,a,b;
int check(int mid)
{
	int s=m/k;
	int r=m%k;
	int ta=a-r,tb=b-s;
	if(ta>=0&&tb>=0) return 1;
	else if(ta>=0)
	{
		//b<0
		int d=0-tb;
		if(a/k)//a/k表示剩余的a能补几个k
		{
			d -= ta/k;
			d=max(0,d);
		}
		if(d<=mid) return 1;
		else return 0;
	}
	else if(tb>=0)
	{
		int d=0-ta;
		if(d<=mid) return 1;
		else return 0;
	}
	else
	{
		int d=0-ta+0-tb;
		if(d<=mid) return 1;
		else return 0;	
	}
}
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d%d%d",&m,&k,&a,&b);
		int l=0,r=m;
		while(l

ps:这题真的很像贪心题,也确实在check的时候用到了贪心策略,但是唯一的贪心就是如果价值为1的普通硬币有多的可以去补价值为k的普通硬币不足的部分,除此之外,本质上考的还是二分,就跟之前那个打饭题一样,看似要找最优策略,实际上只有很简单的一步用到贪心,本质上还是一个二分题,判断二分出来的结果是否合适。

Game on Permutation(Problem - C - Codeforces)

题目大意:有一个排列,A和B做游戏,A先移动,B后移动,A的第一次移动选择将芯片放在某一个数上,剩下的每次移动只能向左,同时移到一个严格小于当前数的数上去,谁不能进行移动,那么谁就赢了,我们将A选择的位置中,A必胜的位置视为幸运位置,问排列中有多少个幸运位置。

思路:很容易发现,我们相当于是找以某个点结尾的单增序列的最长长度,如果长度等于2,那么很显然,B移动一次,轮到A,那么A此时不能移动,胜利,如果等于长度等于1,显然B直接胜利,如果长度大于2,那么B可以将芯片移动到倒数第二个位置,A移动一次,然后B胜利,所以只有长度为2的时候,是幸运位置,但是有一点比较麻烦的是,这题的数据范围是t是1e4,n是3e5,那么需要用线性的时间复杂度来解决。于是就要用单调队列优化的方法处理最长上升子序列。这里我们在为每个字符找出来的r+1实际上也就是以它为结尾的最长上升子序列的长度。

#include
using namespace std;
int a[300010],q[300010],lh[300010],hh,tt;
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
  		int n;
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    	int len=0;
    	for(int i=1;i<=n;i++)
    	{
        	int l=0,r=len;
        	while(l

你可能感兴趣的:(codeforces补题,算法)