【解题报告】CF DIV3 #ROUND 713 A~E

【解题报告】CF DIV3 #ROUND 713 A~E

比赛链接
这次比较稳,3题一发A掉,但是A题没有速A,8000人才通过,排名3900+,分数回涨还行
可能被hack的人比较多吧,结束的时候排5200,出来居然只有3900+

A. Spy Detected!

思路
开局以为只要输出是哪个数,后来发现要输出下标啊啊啊,时间拖延了好多
暴力模拟一遍就完事了
代码

// Problem: A. Spy Detected!
// Contest: Codeforces - Codeforces Round #713 (Div. 3)
// URL: https://codeforces.com/contest/1512/problem/A
// Memory Limit: 256 MB
// Time Limit: 2000 ms
// FishingRod
// 
// Powered by CP Editor (https://cpeditor.org)

#include<bits/stdc++.h>
using namespace std;
#define endl "\n"
typedef long long LL;
typedef pair<int,int> PII;

/*DATA & KEY

*/
int T;
const int N=105;
int a[N];
void solve(int T)
{
	//NEW DATA CLEAN
	map<int,int>mp;
	//NOTE!!!
	int n;cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		mp[a[i]]++;
	}
	int k;
	for(auto t:mp)
		if(t.second==1)
		{
			k=t.first;
			break;
		}
	for(int i=1;i<=n;i++)
		if(k==a[i])
		{
			cout<<i<<endl;
			break;
		}
	
}

int main()
{
	scanf("%d",&T);
	while(T--)solve(T);
	return 0;
}

B. Almost Rectangle

思路
还是模拟,只要形成矩形即可,比较特殊的情况是行或者列相同。需要特殊处理一下。
任意答案所以如果同行或者同列那就尝试两个方向移动一格即可
题解采用了取模的方法来防止出界,也是挺不错的

代码

// Problem: B. Almost Rectangle
// Contest: Codeforces - Codeforces Round #713 (Div. 3)
// URL: https://codeforces.com/contest/1512/problem/B
// Memory Limit: 256 MB
// Time Limit: 2000 ms
// FishingRod
// 
// Powered by CP Editor (https://cpeditor.org)

#include<bits/stdc++.h>
using namespace std;
#define endl "\n"
typedef long long LL;
typedef pair<int,int> PII;

/*DATA & KEY

*/
int T;
const int N=405;
char g[N][N];
void solve(int T)
{
	//NEW DATA CLEAN
	memset(g,0,sizeof g);
	//NOTE!!!
	int n;cin>>n;
	for(int i=0;i<n;i++)cin>>g[i];
	int x1,y1,x2,y2;
	bool flag=1;
	for(int i=0;i<n;i++)
		for(int j=0;j<n;j++)
			if(g[i][j]=='*')
			{
				if(flag)
				{
					x1=i,y1=j,flag=0;
				}
				else x2=i,y2=j;
			}
	g[x1][y2]=g[x2][y1]='*';
	if(x1==x2)
	{
		if(x1+1<n)g[x1+1][y1]=g[x1+1][y2]='*';
		else g[x1-1][y1]=g[x2-1][y2]='*';
	}
	if(y1==y2)
	{
		if(y1+1<n)g[x1][y1+1]=g[x2][y2+1]='*';
		else g[x1][y1-1]=g[x2][y2-1]='*';
	}
	
	for(int i=0;i<n;i++)cout<<g[i]<<endl;
}

int main()
{
	scanf("%d",&T);
	while(T--)solve(T);
	return 0;
}

C. A-B Palindrome

思路
还是模拟,比赛时写的代码比较冗余吧。
大致的思路如下
预处理部分
①把已知的或者可以推测出来的用标记一波(st数组)
②然后再遍历一遍,把可以推测出的问号确定下来,同时判断有没有产生冲突。确定后其实就变成a和b确定,然后给你一个由问号构成的串,看能不能用a个1和b个0构成回文串
构造部分
③统计已经确定的0和1的数量,然后判a和b是否足够,并通过奇偶判能否构成回文串
④有点贪心的操作,0和1哪个多用哪个
代码

// Problem: C. A-B Palindrome
// Contest: Codeforces - Codeforces Round #713 (Div. 3)
// URL: https://codeforces.com/contest/1512/problem/C
// Memory Limit: 256 MB
// Time Limit: 2000 ms
// FishingRod
// 
// Powered by CP Editor (https://cpeditor.org)

#include<bits/stdc++.h>
using namespace std;
#define endl "\n"
typedef long long LL;
typedef pair<int,int> PII;
/*DATA & KEY

*/
int T;
const int N=4E5+10;
int st[N];
void solve(int T)
{
	//NEW DATA CLEAN
	memset(st,-1,sizeof st);
	//NOTE!!!
	int a,b;cin>>a>>b;
	string s;cin>>s;
	for(int i=0;s[i];i++)
	{
		if(s[i]=='0')st[a+b-i-1]=0,st[i]=0;
		else if(s[i]=='1')st[a+b-i-1]=1,st[i]=1;
	}
	bool flag=1;
	for(int i=0;s[i];i++)
	{
		if(s[i]=='?'&&st[i]!=-1)s[i]=('0'+st[i]);
		else if(s[i]=='1'&&st[i]==0)
		{
			puts("-1");flag=0;break;
		}
		else if(s[i]=='0'&&st[i]==1)
		{
			puts("-1");flag=0;break;
		}
	}
	int cnt=0;
	int ta=a,tb=b;
	if(flag)
	{
		for(int i=0;s[i];i++)
		{
			if(s[i]=='0')ta--;
			if(s[i]=='1')tb--;
			if(s[i]=='?')cnt++;
		}

		if(ta<0||tb<0||ta+tb!=cnt||(ta%2==1&&tb%2==1))
		{
			puts("-1");flag=0;
		}
		if(flag)
		{
			for(int i=0;s[i];i++)
			{
				if(s[i]=='?')
				{
					if(ta>tb)//用0
					{
						s[i]='0';ta--;
						if(a+b-1-i!=i)s[a+b-1-i]='0',ta--;
					}
					else
					{
						s[i]='1';tb--;
						if(a+b-1-i!=i)s[a+b-1-i]='1',tb--;
					}
				}
			}
			cout<<s<<endl;
		}
	}
	
	
}
//1?1 012 2
int main()
{
	scanf("%d",&T);
	while(T--)solve(T);
	return 0;
}

D. Corrupted Array

思路
这题比赛的时候没啥思路,看了题解后意识到题目读错了
在这里插入图片描述

区分 b n + 1 = a 1 + a 2 + … … + a n b_{n+1}=a_1+a_2+……+a_n bn+1=a1+a2++an b i + 1 = a 1 + a 2 + … … + a i b_{i+1}=a_1+a_2+……+a_i bi+1=a1+a2++ai啊,小憨憨!
重新梳理一下题意吧!对5个要求逐个分析翻译
给你一个n,和n+2个数,

  1. 然后选两个数(⑤,因为是shuffled所以相当于选数了),
  2. 一个作为x(④)
  3. 一个作为数组a的和(③)
  4. 其他的作为a的元素(②)
  5. 问你能不能构造出a(①)

b n + 1 = S u m a b_{n+1}=Sum_a bn+1=Suma
S u m b = 2 ∗ S u m a + x Sum_b=2*Sum_a+x Sumb=2Suma+x
x = S u m b − 2 ∗ S u m a x=Sum_b-2*Sum_a x=Sumb2Suma
显然的, b n + 1 b_{n+1} bn+1一定是排列后最大的两个中的一个
从小到大排序后
如果 S u m a = b n + 1 Sum_a=b_{n+1} Suma=bn+1,那么 x = b n + 2 x=b_{n+2} x=bn+2
如果 S u m a = b n + 2 Sum_a=b_{n+2} Suma=bn+2,那么 x = S u m b − 2 ∗ b n + 2 x=Sum_b-2*b_{n+2} x=Sumb2bn+2
代码

// Problem: D. Corrupted Array
// Contest: Codeforces - Codeforces Round #713 (Div. 3)
// URL: https://codeforces.com/contest/1512/problem/D
// Memory Limit: 256 MB
// Time Limit: 2000 ms
// FishingRod
// 
// Powered by CP Editor (https://cpeditor.org)

#include<bits/stdc++.h>
using namespace std;
#define endl "\n"
typedef long long LL;
typedef pair<int,int> PII;

/*DATA & KEY

*/
int T;
const int N=2E5+10;
int b[N];
void solve(int T)
{
	//NEW DATA CLEAN
	memset(b,0,sizeof b);
	LL s=0;
	//NOTE!!!
	int n;cin>>n;
	for(int i=1;i<=n+2;i++)
	{
		cin>>b[i];
		s+=b[i];
	}
	sort(b+1,b+3+n);
	
	LL x,sa;
	//第一种
	sa=b[n+1];x=b[n+2];
	if(s-2*sa==x)
	{
		for(int i=1;i<=n;i++)cout<<b[i]<<" ";
		cout<<endl;
		return;
	}
	//第二种
	sa=b[n+2];x=s-2*b[n+2];
	int pos=lower_bound(b+1,b+n+2,x)-b;
	if(pos<=n+1&&b[pos]==x)
	{
		for(int i=1;i<=n+1;i++)
			if(i!=pos)cout<<b[i]<<" ";
		cout<<endl;
		return;
	}
	puts("-1");
}

int main()
{
	scanf("%d",&T);
	while(T--)solve(T);
	return 0;
}

E. Permutation by Sum

思路
输出1~n的一种排列数,使得【L,R】区间和为s,如果不存在就输出-1.
比赛最后看了一眼,想到01背包,但是问题是,如果对L,R区间做背包,如何确定哪些物品作为可选物品?然后就结束了

正解:
首先判有没有可能:对于区间[L,R],s的值最小为1+2+3+……,最大为n+n-1+n-2+……
如果是在区间内那么从最小的1+2+3+……开始逐渐让这些数字变大直到为s
那么如何逐渐让这些数字变大呢
每次用可选的里第一个比a[R]大的数,替换掉a[R],如果没有的话就说明要替换a[R-1]了
然后疯狂写爆啊啊,参考了大佬的博客然后加了些注释

代码

// Problem: E. Permutation by Sum
// Contest: Codeforces - Codeforces Round #713 (Div. 3)
// URL: https://codeforces.com/contest/1512/problem/E
// Memory Limit: 256 MB
// Time Limit: 2000 ms
// FishingRod
// 参考:https://blog.csdn.net/sjjzslhhh/article/details/115598278
// Powered by CP Editor (https://cpeditor.org)

#include<bits/stdc++.h>
using namespace std;
#define endl "\n"
typedef long long LL;
typedef pair<int,int> PII;

/*DATA & KEY
  
*/
int T;
const int N=505;
int a[N];
bool st[N];
void solve(int T)
{
	//NEW DATA CLEAN
	memset(st,0,sizeof st);
	//NOTE!!!
	int n,l,r,s;cin>>n>>l>>r>>s;
	int len=r-l+1;
	LL low=len*(1+r-l+1)/2;
	LL high=len*(n+n-len+1)/2;

	if(s<low||s>high){puts("-1");return;}
	int k=0,t=0,c=l-1;
	k=(s-low)/len,t=(s-low)%len;//原本取模取错了
	for(int i=len;i>=1;i--)
	{
		int d=i;
		if(t)
		{
			d++;
			t--;
		}
		d+=k;
		a[++c]=d;
		st[d]=1;
	}
	//处理[1~l-1]
	int h=0;
	for(int i=1;h<l-1;i++)
	{
		if(!st[i])
		{
			h++;
			cout<<i<<" ";
			st[i]=1;
		}
	}
	for(int i=l;i<=r;i++)cout<<a[i]<<" ";
	for(int i=1;i<=n;i++)
	{
		if(!st[i])
		{
			cout<<i<<" ";
			st[i]=1;
		}
	}
	cout<<endl;
	
}

int main()
{
	scanf("%d",&T);
	while(T--)solve(T);
	return 0;
}

反思

A:

看清题目

B:

取模防止出界,输出任意那就搞个成功概率最大的,移动小一点

C:

先预处理以及标记看有没有冲突,对问题进行化简

D:

分清下标是定值还是变化的
shuffle:打乱的,往往意味着可以把问题转化为选数

E:

对于判断存在结果为某个值的方案,可以先看这个值可能的范围来判断是否存在方案。
一堆数,选n个数来让和为某个值,可以先选最小的,然后逐个增大(让每次变化最小)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值