Codeforces Global Round 12 2/6

比赛链接

A. Avoid Trygub

输入长度为n的字符串s,你可以对字符串进行顺序的调换,保证"trygub"不是新串的子串。
n ≤ 200 n\leq200 n200

输出字典序最小的那个即可。

B. Balls of Steel

给出n个小球的坐标 x i , y i x_i,y_i xi,yi,以及静电的影响范围k。你可以选择任意小球带点,如果一个球带电他就会吸引坐标相减绝对值小于等于k的其余小球。问你要使得全部小球都聚拢在一个坐标,你需要最少让几个球带电,如果无法聚拢输出-1。
2 ≤ n ≤ 100 , k ≤ 1 0 6 , 1 ≤ x i , y i ≤ 1 0 5 2\leq n\leq100,k\leq10^6,1\leq x_i,y_i\leq10^5 2n100,k106,1xi,yi105

如果我们下意识思考,如果我们选定一个点他不能吸到全部的点,那么我们就可以把可以被他吸的点带电,先把别的小球吸过来,再一起吸走。但是再仔细思考,如果一个球可以吸到全部另外一个球无法吸到的球,并且这个球距离也在k之内,那么我为什么要花两次带电机会使得全部聚拢呢,直接使得那个可以吸全部球的带电就行了,如果没有这样的球,使得其他球距离都小于k。就说明永远是无解的。

#include <bits/stdc++.h>
using namespace std;
#define js ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
#define all(__vv__) (__vv__).begin(), (__vv__).end()
#define endl "\n"
#define pai pair<int, int>
#define ms(__x__,__val__) memset(__x__, __val__, sizeof(__x__))
#define rep(i, sta, en) for(int i=sta; i<=en; ++i)
#define repp(i, sta, en) for(int i=sta; i>=en; --i)
typedef long long ll; typedef unsigned long long ull; typedef long double ld;
inline ll read() { ll s = 0, w = 1; char ch = getchar(); for (; !isdigit(ch); ch = getchar()) if (ch == '-') w = -1; for (; isdigit(ch); ch = getchar())	s = (s << 1) + (s << 3) + (ch ^ 48); return s * w; }
inline void print(ll x, int op = 10) { if (!x) { putchar('0'); if (op)	putchar(op); return; }	char F[40]; ll tmp = x > 0 ? x : -x;	if (x < 0)putchar('-');	int cnt = 0;	while (tmp > 0) { F[cnt++] = tmp % 10 + '0';		tmp /= 10; }	while (cnt > 0)putchar(F[--cnt]);	if (op)	putchar(op); }
inline ll gcd(ll x, ll y) { return y ? gcd(y, x % y) : x; }
ll qpow(ll a, ll b) { ll ans = 1;	while (b) { if (b & 1)	ans *= a;		b >>= 1;		a *= a; }	return ans; }	ll qpow(ll a, ll b, ll mod) { ll ans = 1; while (b) { if (b & 1)(ans *= a) %= mod; b >>= 1; (a *= a) %= mod; }return ans % mod; }
const int dir[][2] = { {0,1},{1,0},{0,-1},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1} };
const int MOD = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int N = 100 + 7;

ll n, m;
pai a[N];
#define x first
#define y second

int check(pai A, pai B) {
	return abs(A.x - B.x) + abs(A.y - B.y);
}

void solve() {
	n = read(), m = read();
	rep(i, 1, n)	a[i].x = read(), a[i].y = read();
	rep(i, 1, n) {
		bool flag = 1;
		rep(j, 1, n) {
			if (check(a[i], a[j]) > m)
				flag = 0;
		}
		if (flag) { print(1); return; }
	}
	print(-1);
}

int main() {
	int T = read();	while (T--)
		solve();
	return 0;
}

C1. Errich-Tac-Toe (Easy Version)

给出 n ∗ n n*n nn棋盘,棋盘中有X一种棋子,也还有.(点)代表这个地方没有棋子。现在横着或者竖着三个相同的棋子就会有玩家赢得比赛。现在要你修改m个地方,使得当前格局下没有玩家获胜。m应该小于 ⌊ k 3 ⌋ \lfloor\frac{k}{3}\rfloor 3k,k是起始的棋子数目。

我们把地图下标从0开始编号,使用 ( i + j ) % 3 (i+j)\%3 (i+j)%3对全部的格子进行分类,你会发现我们按照斜线分成三种。我们选择包含棋子最少的那一种格子把他全部变成O,就可以使得X一定无法获得胜利,并且保证了m的要求。

const int N = 300 + 7;
 
ll n, m;
char s[N][N];
int cnt[3];
 
void solve() {
	n = read();
	ms(cnt, 0);
	rep(i, 0, n - 1) {
		scanf("%s", s[i]);
		rep(j, 0, n - 1)
			if (s[i][j] == 'X')	++cnt[(i + j) % 3];
	}
	int pos = min_element(cnt, cnt + 3) - cnt;
	rep(i, 0, n - 1) {
		rep(j, 0, n - 1) {
			int tmp = (i + j) % 3;
			if (s[i][j] == 'X' and tmp == pos)
				putchar('O');
			else putchar(s[i][j]);
		}
		puts("");
	}
}

C2. Errich-Tac-Toe (Hard Version)

困难版本在起始的棋盘会存在X和O两种棋子。
我们同样把棋盘按照位置分隔开,但是我们还要分别统计这个斜线中X的个数以及O的个数。那么同理我们三种样式中,一定有两种是X一种是O或者两种是O一种是X。并且我们发现这样枚举之后任选一个行成为X并且任选另外一个和它不同的下标的成为O,这样就可以保证没玩家胜利。但是如何保证一定满足m的大小要求呢。显然我把全部不同下标的计数器累加起来会得到 2 ∗ k 2*k 2k个格子,相当于省略了k个完全一样的。那么 2 k 6 \frac{2k}{6} 62k是满足题目要求的,只需要找到满足要求的那个解即可。

const int N = 300 + 7;
 
ll n, m;
char s[N][N];
int cnt[3][2];
 
void solve() {
	n = read();
	ms(cnt, 0);
	m = 0;
	rep(i, 0, n - 1) {
		scanf("%s", s[i]);
		rep(j, 0, n - 1) {
			if (s[i][j] == '.')	continue;
			int tmp = (i + j) % 3;
			if (s[i][j] == 'X')	++cnt[tmp][0];
			else ++cnt[tmp][1];
			++m;
		}
	}
	m /= 3;
	rep(i, 0, 2) {
		rep(j, 0, 2) {
			if (i == j)	continue;
			if (cnt[i][0] + cnt[j][1] > m)	continue;
			rep(x, 0, n - 1) {
				rep(y, 0, n - 1) {
					int tmp = (x + y) % 3;
					if (tmp == i and s[x][y] == 'X')	s[x][y] = 'O';
					else if (tmp == j and s[x][y] == 'O')	s[x][y] = 'X';
				}
				puts(s[x]);
			}
			return;
		}
	}
}

D. Rating Compression

给出长度为n的序列,判断选出长度为k的子数组并且求出你找到的子数组最小值,依次从后放入新数组中,如果新数组中构成了一个长度为 n − k + 1 n-k+1 nk+1的全排列说明长度为k的时候答案是1,否则答案是0,要你输出一个长度是n的答案字符串。
n ≤ 3 ∗ 1 0 5 n\leq3*10^5 n3105

首先先看特殊的k。如果k=1,需要判断起始给出的序列是不是全排列。
如果k=n,需要判断序列中是不是存在1。
如果k=n-1,我们首先要判断 a 1 a_1 a1或者 a n a_n an是不是1,假设 a 1 a_1 a1是1,说明我们在[2,n]之间最小值存在2,并且只有一个2。如果 a n a_n an是1,说明我们在[1,n-1]之间存在一个2。
如果k=n-2,我们要先从左边或者右边依次往中间一共走两步并且保证1和2只能出现1次,并且一定要在开始就跨过去这两个点,并且使得中间没有走过的地方存在3。
那么到这里就有点看出规律了。首先要特判k=1,n,接来下就把游标放在左右端点。l=1,r=n。我们依次放入1到n的全排列去判断,假设k=n-2的时候判断失败了,说明k=n-3的时候一定也无解,因为你要把序列分的更碎,这个你判断失败的地方还是要选择长度为2的去生成,仍然无解。只有当k=1的时候这个要特判一下。

const int N = 3e5 + 7;
 
ll n, m;
int a[N];
char s[N];
 
void solve() {
	n = read();
	unordered_map<int, int> mp;
	ms(s, 0);
	rep(i, 1, n) {
		a[i] = read();
		++mp[a[i]];
		s[i] = '0';
	}
	if (mp[1] != 0)	s[n] = '1';
	else {
		puts(s + 1);
		return;
	}
	bool flag = 1;
	rep(i, 1, n)
		if (mp[i] != 1) { flag = 0; break; }
	if (flag)	s[1] = '1';
	int l = 1, r = n;
	rep(i, 1, n) {
		s[n - i + 1] = '1';
		if (mp[i] == 1 and mp[i + 1] != 0 and (a[l] == i or a[r] == i)) {
			if (a[l] == i)	++l;
			else if (a[r] == i)	--r;
			--mp[i];
		}
		else
			break;
	}
	puts(s + 1);
}

E. Capitalism

给出n个点m条边构成的无向图,点权信息不给出需要你进行推理。后面给出边的信息中会存在三个参数 u , v , d u,v,d u,v,d。当d=1时,说明v的点权比u大一,如果d=0,说明v的点权可能比u大一,也可能u的点权比v的点权大一。现在要你给出这个图是不是相邻节点点权相差1,如果可以构造出这样的点权请输出点权相差最大的两个点之间差值是多少。否则输出一个NO。
n ≤ 200 , m ≤ 2000 n\leq200,m\leq2000 n200,m2000

差分约束,我们知道我们相邻的点权一定只相差1,那么如果我们按照点权的奇偶建图会发现我们拿到的可行解一定是一个二分图,那么题目给出的边权信息,我们跑一边,首先判断是不是二分图,如果不是二分图说明无解。
接下来就要看题目给的 d = 1 , a v − a u = 1 d=1,a_v-a_u=1 d=1,avau=1,我们把这个拆分会拿到 a v − a u ≤ 1 a v − a u ≥ 1 → a u − a v ≤ − 1 a_v-a_u\leq1\\a_v-a_u\geq1\to a_u-a_v\leq-1 avau1avau1auav1
因为差分约束系统中要使得不等式符号方向相同,我们做个简单的变形即可。
还要就是 d = 0 , ∣ a v − a u ∣ = 1 d=0,|a_v-a_u|=1 d=0,avau=1,我们分情况讨论。

  1. 如果 a v − a u = 1 a_v-a_u=1 avau=1和上面情况相同
  2. 或者 a u − a v = 1 a_u-a_v=1 auav=1,我们可以解得 a u − a v ≤ 1 a v − a u ≤ − 1 a_u-a_v\leq1\\a_v-a_u\leq-1 auav1avau1进行合并之后会发现我们两点之间得要求就是 a u − a v ≤ 1 a v − a u ≤ 1 a_u-a_v\leq1\\a_v-a_u\leq1 auav1avau1

紧接着跑Floyd就可以拿到最短路,再根据差分约束系统有解条件,不能存在负环。拿到最大值就行了。

const int N = 200 + 7;
 
ll n, m;
int w[N][N];
int fa[N << 1];
int find(int x) { return x == fa[x] ? x : fa[x] = find(fa[x]); }
void merge(int u, int v) {
	int fu = find(u), fv = find(v);
	fa[fv] = fu;
}
 
void solve() {
	n = read(), m = read();
	ms(w, 0x3f);
	rep(i, 1, n << 1)	fa[i] = i;
	rep(i, 1, n)	w[i][i] = 0;
	while (m--) {
		int u = read(), v = read(), d = read();
		if (d) {
			w[u][v] = 1;
			w[v][u] = -1;
		}
		else {
			w[u][v] = 1;
			w[v][u] = 1;
		}
		merge(u, v + n);
		merge(v, u + n);
	}
	rep(i, 1, n) {
		if (fa[i] == fa[i + n]) {
			puts("NO");
			return;
		}
	}
	rep(k, 1, n)
		rep(i, 1, n)
		rep(j, 1, n)
		w[i][j] = min(w[i][j], w[i][k] + w[k][j]);
	int st, maxi = -INF;
	rep(i, 1, n) {
		if (w[i][i] < 0) {
			puts("NO");
			return;
		}
		rep(j, 1, n) {
			if (w[i][j] > maxi)
				maxi = w[i][j],
				st = i;
		}
	}
	puts("YES");
	print(maxi);
	rep(j, 1, n)
		print(w[st][j], " \n"[j == n]);
}

F. The Struggling Contestant

给你长度为n的序列,要你重新排序之后使得新的序列中不存在相邻两个数相同。输出新排列中 ∑ i = 1 j = i + 1 ∣ i − j ∣ > 1 ? 1 : 0 \sum\limits^{j=i+1}_{i=1}|i-j|>1?1:0 i=1j=i+1ij>1?1:0,既排列后新的序列中相邻两个位置之前的原下标差距大于1的和是多少。如果无法使得新序列中不存在相邻数输出-1。
n ≤ 1 0 5 n\leq10^5 n105

先判断输出-1的情况,那就是插空法,不足以完全分开。判断下是不是那个数出现次数大于了 n + 1 2 \frac{n+1}{2} 2n+1。首先我们看13441,我们一定是把41一起放到最前面去形成14134,答案是1。那么通过这个我们可以发现,相同的数之间一定要插入一个数或者一段数,并且如果可以插入一段数不会选择这一段数里面的单独一个数。那么我们就可以使用分段把这个待处理的序列拆分掉。使用一个 f [ n ] f[n] f[n]代表n做为分隔端点的次数,如果 a i = a i − 1 a_i=a_{i-1} ai=ai1说明 a i a_i ai做为端点出现次数要+2,还有天然的端点 a 1 a_1 a1 a n a_n an这两个做为端点出现次数也要+1。

那么我们的答案就是 k + max ⁡ ( 0 , ( max ⁡ i = 1 n f i ) − k − 2 ) k+\max(0,(\max\limits_{i=1}^n f_i)-k-2) k+max(0,(i=1maxnfi)k2)
k是 a i = a i − 1 a_i=a_{i-1} ai=ai1的计数器,存在3对相同的数,一定需要3为最小值。因为你要从别的地方插入一个去中间,那么无论是把左边端点还是右边端点插入,都一定会存在1的贡献,那么k对数就是合理划分就是k的贡献。那么什么时候会需要额外加一些答案,那就是一个数做为端点最多的那个数,即使把他放在两端用掉两个天然的端点并且使用其余的端点无法拆分之后,你就需要从这一段数中间拿出一个数出去接着分。这样的时候答案贡献就要额外+1。那么我们找到最多需要几个这样的额外答案即可。

const int N = 1e5 + 7;
 
ll n, m;
int a[N], f[N];
 
void solve() {
	n = read();
	ms(a, 0);
	ms(f, 0);
	unordered_map<int, int> mp;
	m = 0;
	int maxi = 0;
	rep(i, 1, n) {
		a[i] = read();
		++mp[a[i]];
		maxi = max(maxi, mp[a[i]]);
		if (a[i] == a[i - 1])
			f[a[i]] += 2, ++m;
	}
	if (maxi > (n + 1) / 2)	print(-1);
	else {
		++f[a[1]]; ++f[a[n]];
		ll tmp = max(0ll, *max_element(f + 1, f + n + 1) - m - 2);
		m += tmp;
		print(m);
	}
}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
系统根据B/S,即所谓的电脑浏览器/网络服务器方式,运用Java技术性,挑选MySQL作为后台系统。系统主要包含对客服聊天管理、字典表管理、公告信息管理、金融工具管理、金融工具收藏管理、金融工具银行卡管理、借款管理、理财产品管理、理财产品收藏管理、理财产品银行卡管理、理财银行卡信息管理、银行卡管理、存款管理、银行卡记录管理、取款管理、转账管理、用户管理、员工管理等功能模块。 文中重点介绍了银行管理的专业技术发展背景和发展状况,随后遵照软件传统式研发流程,最先挑选适用思维和语言软件开发平台,依据需求分析报告模块和设计数据库结构,再根据系统功能模块的设计制作系统功能模块图、流程表和E-R图。随后设计架构以及编写代码,并实现系统能模块。最终基本完成系统检测和功能测试。结果显示,该系统能够实现所需要的作用,工作状态没有明显缺陷。 系统登录功能是程序必不可少的功能,在登录页面必填的数据有两项,一项就是账号,另一项数据就是密码,当管理员正确填写并提交这二者数据之后,管理员就可以进入系统后台功能操作区。进入银行卡列表,管理员可以进行查看列表、模糊搜索以及相关维护等操作。用户进入系统可以查看公告和模糊搜索公告信息、也可以进行公告维护操作。理财产品管理页面,管理员可以进行查看列表、模糊搜索以及相关维护等操作。产品类型管理页面,此页面提供给管理员的功能有:新增产品类型,修改产品类型,删除产品类型。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值