Codeforces Round #631 (Div. 2)

Posted zhltao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #631 (Div. 2)相关的知识,希望对你有一定的参考价值。

这场打的有点小开心呀,最后交过 T4 ,但是T3 的线段树居然炸了,也不知道是为啥....反正拿 (O(n)) 做法搞过去了....

技术图片

Problem A

没什么好说的,随便瞎搞

#include <bits/stdc++.h>

using namespace std;

template <typename T>
inline T read()
{
	T x = 0;
	char ch = getchar();
	bool f = 0;
	while(ch < ‘0‘ || ch > ‘9‘)
	{
		f = (ch == ‘-‘);
		ch = getchar();
	}
	while(ch <= ‘9‘ && ch >= ‘0‘)
	{
		x = (x << 1) + (x << 3) + (ch - ‘0‘);
		ch = getchar();
	}
	return  f? -x : x;
}

template <typename T>
void put(T x)
{
	if(x < 0)
	{
		x = -x;
		putchar(‘-‘);
	}
	if(x < 10) {
		putchar(x + 48);
		return;
	}
	put(x / 10);
	putchar(x % 10 + 48);
	return ;
}

#define rd read <int>
#define pt(i) put <int> (i), putchar(‘
‘)
#define ptY puts("YES")
#define ptN puts("NO") 

typedef long long ll;
typedef double db;
typedef long double ldb;
typedef unsigned long long ull;
typedef unsigned int ui;

const int Maxn = 2e2 + 111;

int x, t, n;

bool flag[Maxn];

int main()
{
#ifdef _DEBUG
	freopen("in.txt", "r", stdin);
#endif
	t = rd();
	while(t--)
	{
		memset(flag, 0, sizeof flag);
		n = rd(); x = rd();
		for(int i = 1; i <= n; ++i)
			flag[rd()] = 1;
		int len = 0;
		while(x > 0 || flag[len + 1])
		{
			if(!flag[len + 1]) --x;
			len++;
		}
		pt(len);
	}
	return 0;
}

Problem B

这题吗,就是注意到 (Max_{ans} = 2),注意判一下两个一样

#include <bits/stdc++.h>

using namespace std;

template <typename T>
inline T read()
{
	T x = 0;
	char ch = getchar();
	bool f = 0;
	while(ch < ‘0‘ || ch > ‘9‘)
	{
		f = (ch == ‘-‘);
		ch = getchar();
	}
	while(ch <= ‘9‘ && ch >= ‘0‘)
	{
		x = (x << 1) + (x << 3) + (ch - ‘0‘);
		ch = getchar();
	}
	return  f? -x : x;
}

template <typename T>
void put(T x)
{
	if(x < 0)
	{
		x = -x;
		putchar(‘-‘);
	}
	if(x < 10) {
		putchar(x + 48);
		return;
	}
	put(x / 10);
	putchar(x % 10 + 48);
	return ;
}

#define rd read <int>
#define pt(i) put <int> (i), putchar(‘
‘)

typedef long long ll;
typedef double db;
typedef long double ldb;
typedef unsigned long long ull;
typedef unsigned int ui;

const int Maxn = 2e5 + 111;

int t, a[Maxn], cnt[Maxn], n, max1, ans;

int main()
{
#ifdef _DEBUG
	freopen("in.txt", "r", stdin);
#endif
	t = rd();
	while(t--)
	{
		n = rd();
		max1 = 0;
		for(int i = 1; i <= n; ++i)
		{
			a[i] = rd();
			max1 = max(max1, a[i]);
		}
		memset(cnt, 0, sizeof cnt);
		for(int i = 1; i <= max1; ++i) cnt[a[i]]++;
		bool flag = 0;
		ans = 0;
		for(int i = 1; i <= max1; ++i)
			if(cnt[i] != 1)
			{
				flag = 1;
				break;
			}
		if(!flag)
		{
			memset(cnt, 0, sizeof cnt);
			for(int i = max1 + 1; i <= n; ++i) cnt[a[i]]++;
			for(int i = 1; i <= n - max1; ++i)
				if(cnt[i] != 1)
				{
					flag = 1;
					break;
				}
		}
		ans += !flag;
		bool flag1 = 0;
		memset(cnt, 0, sizeof cnt);
		for(int i = 1; i <= max1; ++i) cnt[a[n - i + 1]]++;
		for(int i = 1; i <= max1; ++i) if(cnt[i] != 1) { flag1 = 1;break;}
		if(!flag1)
		{
			memset(cnt, 0, sizeof cnt);
			for(int i = 1; i <= n - max1; ++i) cnt[a[i]]++;
			for(int i = 1; i <= n - max1; ++i)
				if(cnt[i] != 1)
				{
					flag1 = 1;
					break;
				}
		}
		ans += !flag1;
		if(!flag1 && !flag && n % 2 == 0 && max1== n / 2)
		{
			pt(1);
			put(max1);
			putchar(‘ ‘);
			pt(n - max1);
			continue;
		}
		pt(ans);
		if(!flag)
		{
			put(max1);
			putchar(‘ ‘);
			pt(n - max1);
		}
		if(!flag1)
		{
			put(n - max1);
			putchar(‘ ‘);
			pt(max1);
		}
	}
	return 0;
}

Problem C

随便瞎搞就行了,考虑覆盖,记下起点与终点

#include <bits/stdc++.h>

using namespace std;

template <typename T>
inline T read() {
  T x = 0;
  char ch = getchar();
  bool f = 0;
  while (ch < ‘0‘ || ch > ‘9‘) {
    f = (ch == ‘-‘);
    ch = getchar();
  }
  while (ch <= ‘9‘ && ch >= ‘0‘) {
    x = (x << 1) + (x << 3) + (ch - ‘0‘);
    ch = getchar();
  }
  return f ? -x : x;
}

template <typename T>
void put(T x) {
  if (x < 0) {
    x = -x;
    putchar(‘-‘);
  }
  if (x < 10) {
    putchar(x + 48);
    return;
  }
  put(x / 10);
  putchar(x % 10 + 48);
  return;
}

#define rd read<int>
#define pt(i) put<int>(i), putchar(‘ ‘)

typedef long long ll;
typedef double db;
typedef long double ldb;
typedef unsigned long long ull;
typedef unsigned int ui;
const int Maxn = 2e5 + 111;

int n, m, l[Maxn], p[Maxn], oo = 0;
int main() {
  n = rd();
  m = rd();
  for (int i = 1; i <= m; ++i) l[i] = rd();
  int coo;
  for (int i = m; i >= 1; --i) {
    coo = min(l[i], n - oo - i + 1);
    if (coo <= 0) {
      printf("-1
");
      return 0;
		}
    p[i] = max(1, oo + coo - l[i] + 1);
    oo = p[i] + l[i] - 1;
  }
  if (oo != n) {
    printf("-1");
    return 0;
	}
  for (int i = 1; i <= m; ++i) pt(p[i]);
  return 0;
}

或说,我真正要说的是 D 题,说一个非常愉悦的 dp 想法

Problem D

考虑一个性质,我们可以证明

定义 (p_(i))(a_i) 的位数(即最高位一)

[p(i) > p(i - 1) ]

只要满足这个就有题目条件成立,于是我们可以设计状态 (f[i][j]) 表示在 前 (i) 位的数里只选了 (j) 个,那么我们的所求即为 (sum_{1le i le cnt} f[cnt][i]) 。于是很显然的列出状态转移方程

[f[i][j] = egin{cases} 0 & j = 0 f[i - 1][j - 1] * b[i] + f[i - 1][j] end{cases} ]

其中,(b[i]) 表示 这一位中能选几个

#include <bits/stdc++.h>

using namespace std;

template <typename T>
inline T read()
{
	T x = 0;
	char ch = getchar();
	bool f = 0;
	while(ch < ‘0‘ || ch > ‘9‘)
	{
		f = (ch == ‘-‘);
		ch = getchar();
	}
	while(ch <= ‘9‘ && ch >= ‘0‘)
	{
		x = (x << 1) + (x << 3) + (ch - ‘0‘);
		ch = getchar();
	}
	return  f? -x : x;
}

template <typename T>
void put(T x)
{
	if(x < 0)
	{
		x = -x;
		putchar(‘-‘);
	}
	if(x < 10) {
		putchar(x + 48);
		return;
	}
	put(x / 10);
	putchar(x % 10 + 48);
	return ;
}

#define rd read <long long>
#define pt(i) put <long long> (i), putchar(‘
‘)

typedef long long ll;
typedef double db;
typedef long double ldb;
typedef unsigned long long ull;
typedef unsigned int ui;

const int Maxn = 111;

ll b[40], n, d, f[Maxn][Maxn], cnt, t;

bool flag;

int main()
{
#ifdef _DEBUG
	freopen("in.txt", "r", stdin);
#endif
	t = rd();
	while(t--)
	{
		n = rd();
		flag = 0;
		d = rd();
		b[1] = 1;
		cnt = 1;
		n -= 1;
		for(int i = 1 + 1; i <= 31 && n > 0; ++i)
		{
			b[i] = b[i - 1] << 1;
			n -= b[i];
			if(n <= 0)
			{
				cnt = i;
				b[i] += n;
			}
		}
		f[0][0] = 1;
		for(int i = 1; i <= cnt; ++i)
		{
			f[i][0] = 1;
			for(int j = 1; j <= i; ++j)
				f[i][j] = (f[i - 1][j - 1] * b[i] % d + f[i - 1][j]) % d;
		}
		ll ans = 0;
		for(int i = 1; i <= cnt; ++i) ans = (ans + f[cnt][i]) % d;
		pt(ans);
	} 	
	return 0;
}

这几场确实上分比较快,因为由于某种原因,打的人比较多...

以上是关于Codeforces Round #631 (Div. 2)的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces Round #344 (Div. 2) 631 C. Report (单调栈)

Codeforces Round #631 (Div. 2) B. Dreamoon Likes Permutations(排列组合)

Codeforces Round #631 (Div. 2) - Thanks, Denis aramis Shitov!

Codeforces Round #631 (Div. 2) - Thanks, Denis aramis Shitov!

Codeforces Round #631 (Div. 2) Dreamoon Likes Sequences

Codeforces Round #631 (Div. 2) C. Dreamoon Likes Coloring(贪心好题/意识流题解)