Codeforces Round #631 (Div. 2) 题解

A. Dreamoon and Ranking Collection

题目大意:给你一个数组,你能向添加 x x x个数问添加之后能达到的最大的 v v v是多少,要求从 1 1 1- v v v都能在数组中找到。

题解:由于数据较小,我们可以直接先把数组中的数字放到一个集合中,然后从 1 1 1开始遍历如果在集合中找不到,就让 x − 1 x-1 x1,知道用完 x x x为止。

#include 
 
using namespace std;
 
#define mem(a, x) memset(a, x, sizeof(a))
#define IOS std::ios::sync_with_stdio(false)
#define ls o<<1
#define rs o<<1|1
#define test(a) cout<
#define exp 0.000001
typedef long long ll;
const int mod = 1e9+7;
const int maxn = 1e7 + 5;
const int inf = 0x3f3f3f3f;
 
int a[105];
set<int> si;
void solve()
{
int n,x;
si.clear();
scanf("%d%d",&n,&x);
for(int i=1;i<=n;i++){
	scanf("%d",&a[i]);
	si.insert(a[i]);
}
int ans[205]={0};
int anss=0;
for(int i=1;i<=205;i++)
{
	if(si.count(i))
		ans[i]=ans[i-1];
	else {
		ans[i]=ans[i-1]+1;
		if(ans[i]==x+1){
			anss=i-1;
			break;
		}
	}
}
printf("%d\n",anss);
}
int main()
{
    int t;scanf("%d",&t);while(t--)
    solve();
	return 0;
}

B - Dreamoon Likes Permutations

题目大意:给你一个数组,你需要找到一个分界线使得它的左右两边都是一个排列,并要找出所有的答案。

题解:我们从一号位开始找,记录当前的最大值,如果遇到重复的了,直接结束循环,如果当前最大值和当前位置相等,判断一下剩下的是不是一个排列。

代码:

#include 
 
using namespace std;
 
#define mem(a, x) memset(a, x, sizeof(a))
#define IOS std::ios::sync_with_stdio(false)
#define ls o<<1
#define rs o<<1|1
#define test(a) cout<
#define exp 0.000001
typedef long long ll;
const int mod = 1e9+7;
const int maxn = 2e5 + 5;
const int inf = 0x3f3f3f3f;
 
int a[maxn];
set<int> lsi;
set<int> rsi;
void solve()
{
int n;
lsi.clear();
rsi.clear();
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
	scanf("%d",&a[i]);
}
int cnt=0;
int l[3],r[3];
int lmax=0,rmax=0;
for(int i=1;i<=n;i++)
{
if(lsi.count(a[i]))
	break;
lsi.insert(a[i]);
lmax=max(lmax,a[i]);
if(i==lmax)
{
	//test(i);
	rsi.clear();
	rmax=0;
	int j;
	for(j=i+1;j<=n;j++)
	{
    if(rsi.count(a[j]))
	break;
    rsi.insert(a[j]);
    rmax=max(rmax,a[j]);
	}
	if(j==n+1&&rmax==n-i)
	{
		l[++cnt]=i;
		r[cnt]=n-i;
	}
}
}
printf("%d\n",cnt);
for(int i=1;i<=cnt;i++)
	printf("%d %d\n",l[i],r[i]);
}
int main()
{
    int t;scanf("%d",&t);while(t--)
    solve();
	return 0;
}

C - Dreamoon Likes Coloring

题目大意:你有 n n n个格子和 m m m种颜色,每一种颜色需要涂连续的 l i li li个格子。后涂的颜色会覆盖掉之前的颜色,你需要找到一种涂法使得每一个格子都有颜色且每一种颜色都有在格子上。

题解:首先你得判断所有颜色要涂的格子和是不是大于总格子数,如果不是直接输出 − 1 -1 1。然后因为它要求每一种颜色都有露在外面的,我们可以用贪心的思想,先让每一种颜色都露出一个。直到剩余的颜色暗不重叠的涂法正好涂满。如果不能正好涂满超出了范围也要输出 − 1 -1 1

代码:

#include 
 
using namespace std;
 
#define mem(a, x) memset(a, x, sizeof(a))
#define IOS std::ios::sync_with_stdio(false)
#define ls o<<1
#define rs o<<1|1
#define test(a) cout<
#define exp 0.000001
typedef long long ll;
const int mod = 1e9+7;
const int maxn = 2e5 + 5;
const int inf = 0x3f3f3f3f;
 
 
int a[maxn];
ll sum[maxn];
int ans[maxn];
void solve()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
scanf("%d",&a[i]);
for(int i=m;i>=1;i--)
	sum[i]=sum[i+1]+a[i];
if(sum[1]<n)
	printf("-1\n");
else {
ans[1]=1;
int r=a[1];
for(int i=2;i<=m;i++)
{
	if(sum[i]>=n-r&&sum[i]<=n-i+1)
	{
    int temp=sum[i]-n+r;
    ans[i]=r+1-temp;
    int next=ans[i]+a[i];
    for(int j=i+1;j<=m;j++)
    {
    	ans[j]=next;
    	next=ans[j]+a[j];
    }
    break;
	}
	else {
		ans[i]=i;
		r=max(r,i+a[i]-1);
		if(r>n)
		{
			printf("-1\n");
			return ;
		}
	}
}
for(int i=1;i<=m;i++)
{
if(i!=m)
printf("%d ",ans[i]);
else printf("%d\n",ans[i]);
}
}
}
int main()
{
   // int t;scanf("%d",&t);while(t--)
    solve();
	return 0;
}

写博客写到一半发现我B题被FST了,气死我了,但是我不想改了,你们不要看我B题的口胡做法。睡觉去了。

你可能感兴趣的:(Codeforces Round #631 (Div. 2) 题解)