Atcoder Grand Contest 006 题解

A - Prefix and Suffix

模拟。

//waz
#include <bits/stdc++.h>
 
using namespace std;
 
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define ALL(x) (x).begin(), (x).end()
#define SZ(x) ((int)((x).size()))
 
typedef pair<int, int> PII;
typedef vector<int> VI;
typedef long long int64;
typedef unsigned int uint;
typedef unsigned long long uint64;
 
#define gi(x) ((x) = F())
#define gii(x, y) (gi(x), gi(y))
#define giii(x, y, z) (gii(x, y), gi(z))
 
int F()
{
	char ch;
	int x, a;
	while (ch = getchar(), (ch < '0' || ch > '9') && ch != '-');
	if (ch == '-') ch = getchar(), a = -1;
	else a = 1;
	x = ch - '0';
	while (ch = getchar(), ch >= '0' && ch <= '9')
		x = (x << 1) + (x << 3) + ch - '0';
	return a * x;
}
 
char s[110], t[110];
 
int N;
 
int main()
{
	gi(N);
	scanf("%s", s + 1);
	scanf("%s", t + 1);
	for (int i = N; i; --i)
	{
		int flag = 1;
		for (int j = 1; j <= i; ++j)
			if (s[N - i + j] != t[j])
				flag = 0;
		if (flag)
		{
			printf("%d\n", N + N - i);
			return 0;
		}
	}
	printf("%d\n", N + N);
	return 0;
}

  

B - Median Pyramid Easy

在n和n+1处构造出两个相同的肯定会一直传递到顶。

//waz
#include <bits/stdc++.h>
 
using namespace std;
 
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define ALL(x) (x).begin(), (x).end()
#define SZ(x) ((int)((x).size()))
 
typedef pair<int, int> PII;
typedef vector<int> VI;
typedef long long int64;
typedef unsigned int uint;
typedef unsigned long long uint64;
 
#define gi(x) ((x) = F())
#define gii(x, y) (gi(x), gi(y))
#define giii(x, y, z) (gii(x, y), gi(z))
 
int F()
{
	char ch;
	int x, a;
	while (ch = getchar(), (ch < '0' || ch > '9') && ch != '-');
	if (ch == '-') ch = getchar(), a = -1;
	else a = 1;
	x = ch - '0';
	while (ch = getchar(), ch >= '0' && ch <= '9')
		x = (x << 1) + (x << 3) + ch - '0';
	return a * x;
}
 
int ans[200010], vis[200010];
 
int main()
{
	int n, x;
	gii(n, x);
	if (n == 2)
	{
		if (x == 2)
		{
			printf("Yes\n1\n2\n3\n");
			return 0;
		}
		puts("No");
		return 0;
	}
	int round = n;
	n <<= 1;
	--n;
	int A = n - x, B = x - 1;
	if (B >= 1 && A >= 2)
	{
		ans[round] = x;
		ans[round + 1] = x - 1;
		ans[round - 1] = x + 1;
		ans[round + 2] = x + 2;
		vis[x] = vis[x + 1] = vis[x - 1] = vis[x + 2] = 1;
		int t = 0;
		for (int i = 1; i <= n; ++i)
		{
			while (ans[t + 1]) ++t;
			if (!vis[i]) ans[++t] = i;
		}
		puts("Yes");
		for (int i = 1; i <= n; ++i)
			printf("%d\n", ans[i]);
		return 0;
	}
	else if (B >= 2 && A >= 1)
	{
		ans[round] = x;
		ans[round + 1] = x + 1;
		ans[round - 1] = x - 1;
		ans[round + 2] = x - 2;
		vis[x] = vis[x + 1] = vis[x - 1] = vis[x - 2] = 1;
		int t = 0;
		for (int i = 1; i <= n; ++i)
		{
			while (ans[t + 1]) ++t;
			if (!vis[i]) ans[++t] = i;
		}
		puts("Yes");
		for (int i = 1; i <= n; ++i)
			printf("%d\n", ans[i]);
		return 0;
	}
	puts("No");
	return 0;
}

  

C - Rabbit Exercise

跳一次就相当于差分数组两个位置交换一下,这是个排列的置换,可以快速幂优化。

//waz
#include <bits/stdc++.h>
 
using namespace std;
 
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define ALL(x) (x).begin(), (x).end()
#define SZ(x) ((int)((x).size()))
 
typedef pair<int, int> PII;
typedef vector<int> VI;
typedef long long int64;
typedef unsigned int uint;
typedef unsigned long long uint64;
 
#define gi(x) ((x) = F())
#define gii(x, y) (gi(x), gi(y))
#define giii(x, y, z) (gii(x, y), gi(z))
 
int F()
{
	char ch;
	int x, a;
	while (ch = getchar(), (ch < '0' || ch > '9') && ch != '-');
	if (ch == '-') ch = getchar(), a = -1;
	else a = 1;
	x = ch - '0';
	while (ch = getchar(), ch >= '0' && ch <= '9')
		x = (x << 1) + (x << 3) + ch - '0';
	return a * x;
}
 
const int N = 100010;
 
void mul(int *a, int *b, int n)
{
	static int t[N], h[N];
	for (int i = 1; i <= n; ++i) t[i] = a[i], h[i] = b[i];
	for (int i = 1; i <= n; ++i) a[i] = t[h[i]];
}
 
void fpow(int *a, int n, long long k)
{
	static int t[N];
	for (int i = 1; i <= n; ++i) t[i] = i;
	for (; k; k >>= 1)
	{
		if (k & 1) mul(t, a, n);
		mul(a, a, n);
	}
	for (int i = 1; i <= n; ++i) a[i] = t[i];
}
 
int n;
 
long long x[N];
 
int m, a[N];
 
long long k;
 
int main()
{	
	gi(n);
	for (int i = 1; i <= n; ++i) gi(x[i]), a[i] = i;
	for (int i = n; i; --i) x[i] -= x[i - 1];
	gi(m);
	scanf("%lld", &k);
	for (int i = 1; i <= m; ++i)
	{
		int p;
		gi(p);
		swap(a[p], a[p + 1]);
	}
	fpow(a, n, k);
	for (int i = 1; i <= n; ++i)
	{
		//cerr << a[i] << " : " << x[a[i]] << endl;
		x[a[i]] += x[a[i - 1]];
		printf("%lld\n", x[a[i]]);
	}
	return 0;
}

  

D - Median Pyramid Hard

二分答案,01抵消掉,最近的连续的就是答案。

//waz
#include <bits/stdc++.h>
 
using namespace std;
 
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define ALL(x) (x).begin(), (x).end()
#define SZ(x) ((int)((x).size()))
 
typedef pair<int, int> PII;
typedef vector<int> VI;
typedef long long int64;
typedef unsigned int uint;
typedef unsigned long long uint64;
 
#define gi(x) ((x) = F())
#define gii(x, y) (gi(x), gi(y))
#define giii(x, y, z) (gii(x, y), gi(z))
 
int F()
{
	char ch;
	int x, a;
	while (ch = getchar(), (ch < '0' || ch > '9') && ch != '-');
	if (ch == '-') ch = getchar(), a = -1;
	else a = 1;
	x = ch - '0';
	while (ch = getchar(), ch >= '0' && ch <= '9')
		x = (x << 1) + (x << 3) + ch - '0';
	return a * x;
}
 
const int N = 2e5 + 10;
 
int n, a[N];
 
bool check(int mid)
{
	for (int i = 1; i <= n - 1; ++i)
	{
		if ((a[n + i - 1] >= mid) == (a[n + i] >= mid)) return a[n + i] >= mid;
		if ((a[n - i + 1] >= mid) == (a[n - i] >= mid)) return a[n - i] >= mid;
	}
	return a[1] >= mid;
}
 
int main()
{
	gi(n);
	for (int i = 1; i <= 2 * n - 1; ++i) gi(a[i]);
	int x = 1, v = 2 * n - 1;
	for (int i = 19; ~i; --i)
		if (x + (1 << i) <= v && check(x + (1 << i)))
			x += 1 << i;
	printf("%d\n", x);
}

  

E - Rotate 3x3

首先一列本质就是一个数字带有正反。

算一下移动次数和翻转次数的奇偶性判断一下即可。

//waz
#include <bits/stdc++.h>
 
using namespace std;
 
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define ALL(x) (x).begin(), (x).end()
#define SZ(x) ((int)((x).size()))
 
typedef pair<int, int> PII;
typedef vector<int> VI;
typedef long long int64;
typedef unsigned int uint;
typedef unsigned long long uint64;
 
#define gi(x) ((x) = F())
#define gii(x, y) (gi(x), gi(y))
#define giii(x, y, z) (gii(x, y), gi(z))
 
int F()
{
	char ch;
	int x, a;
	while (ch = getchar(), (ch < '0' || ch > '9') && ch != '-');
	if (ch == '-') ch = getchar(), a = -1;
	else a = 1;
	x = ch - '0';
	while (ch = getchar(), ch >= '0' && ch <= '9')
		x = (x << 1) + (x << 3) + ch - '0';
	return a * x;
}
 
const int N = 1e5 + 10;;
 
int a[3][N], n, s[N], d[N], p[N], cnt[2], ds[2];
 
int tree[N];
 
void change(int x) { for (; x; x -= x & -x) ++tree[x]; }
 
int query(int x) { int v = 0; for (; x <= n; x += x & -x) v += tree[x]; return v; }
 
int main()
{
	gi(n);
	for (int j = 0; j < 3; ++j)
		for (int i = 1; i <= n; ++i)
			gi(a[j][i]);
	for (int i = 1; i <= n; ++i)
	{
		if (a[0][i] == a[1][i] + 1 && a[1][i] == a[2][i] + 1) s[i] = a[0][i] / 3, d[i] = 1;
		else if (a[0][i] == a[1][i] - 1 && a[1][i] == a[2][i] - 1) s[i] = a[2][i] / 3, d[i] = 0;
		else return puts("No"), 0;
		if ((s[i] & 1) != (i & 1)) return puts("No"), 0;
		cnt[i & 1] += d[i];
	}
	for (int i = 1; i <= n; ++i) p[s[i]] = i;
	for (int i = 1; i <= n; i += 2) 
	{
		int now = p[i] + (query(p[i]) << 1);
		ds[1] += (abs(now - i) >> 1) & 1;
		change(p[i]);
	}
	memset(tree, 0, sizeof tree);
	for (int i = 2; i <= n; i += 2)
	{
		int now = p[i] + (query(p[i]) << 1);
		ds[0] += (abs(now - i) >> 1) & 1;
		change(p[i]);
	}
	if ((cnt[0] & 1) != (ds[1] & 1) || (cnt[1] & 1) != (ds[0] & 1)) return puts("No"), 0;
	puts("Yes");
	return 0;
}

  

F - Blackout

本质是一个有向图问题,我们将图染成三种颜色做一下就好了。

//waz
#include <bits/stdc++.h>
 
using namespace std;
 
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define ALL(x) (x).begin(), (x).end()
#define SZ(x) ((int)((x).size()))
 
typedef pair<int, int> PII;
typedef vector<int> VI;
typedef long long int64;
typedef unsigned int uint;
typedef unsigned long long uint64;
 
#define gi(x) ((x) = F())
#define gii(x, y) (gi(x), gi(y))
#define giii(x, y, z) (gii(x, y), gi(z))
 
int F()
{
	char ch;
	int x, a;
	while (ch = getchar(), (ch < '0' || ch > '9') && ch != '-');
	if (ch == '-') ch = getchar(), a = -1;
	else a = 1;
	x = ch - '0';
	while (ch = getchar(), ch >= '0' && ch <= '9')
		x = (x << 1) + (x << 3) + ch - '0';
	return a * x;
}
 
const int N = 1e5 + 10;
 
int n, m;
 
vector<int> e1[N], e2[N]; 
 
bool vis[N];
 
int co[N], flag, cnt[3], s, e;
 
void dfs(int u)
{
	vis[u] = 1;
	++s;
	++cnt[co[u]];
	for (auto v : e1[u])
	{
		++e;
		if (vis[v])
		{
			if (co[v] != (co[u] + 1) % 3)
				flag = 0;
			continue;
		}
		co[v] = (co[u] + 1) % 3;
		dfs(v);		
	}
	for (auto v : e2[u])
	{
		if (vis[v])
		{
			if (co[v] != (co[u] + 2) % 3)
				flag = 0;
			continue;
		}
		co[v] = (co[u] + 2) % 3;
		dfs(v);
	}
}
 
long long ans;
 
int main()
{
	gii(n, m);
	for (int i = 1; i <= m; ++i)
	{
		int u, v;
		gii(u, v);
		e1[u].pb(v);
		e2[v].pb(u);
	}
	for (int i = 1; i <= n; ++i)
	{
		if (!vis[i])
		{
			e = 0;
			s = 0;
			flag = 1;
			cnt[0] = cnt[1] = cnt[2] = 0;
			dfs(i);
			if (!flag)
			{
				ans += 1LL * s * s;
			}
			else if (cnt[0] && cnt[1] && cnt[2])
			{
				ans += 1LL * cnt[0] * cnt[1] + 1LL * cnt[1] * cnt[2] + 1LL * cnt[0] * cnt[2];
			}
			else ans += e;
		}
	}
	printf("%lld\n", ans);
	return 0;
}

  

 

转载于:https://www.cnblogs.com/AnzheWang/p/9624230.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值