ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

2022牛客寒假算法基础集训营3 ABCDEGIL

2022-01-29 01:04:09  阅读:156  来源: 互联网

标签:include int 旋转 牛客 2022 集训营 节点 dp define


A. 智乃的Hello XXXX

随便输出Hello xxx即可。

B. 智乃买瓜

链接:https://ac.nowcoder.com/acm/contest/23478/B
来源:牛客网

题目描述

有一人前来买瓜。
“哥们儿,这瓜多少钱一斤呐”
“两块钱一斤”
“What's up,这瓜皮是金子做的,还是瓜粒子是金子做的”

智乃来到水果摊前买瓜,水果摊上贩卖着NN个不同的西瓜,第ii个西瓜的重量为wiwi。智乃对于每个瓜都可以选择买一个整瓜或者把瓜劈开买半个瓜,半个瓜的重量为wi22wi。

也就是说对于每个西瓜,智乃都有三种不同的决策:

  1. 购买一整个重量为wiwi的西瓜
  2. 把瓜劈开,购买半个重量为wi22wi的西瓜
  3. 不进行购买操作

为了简化题目,我们保证所有瓜的重量都是一个正偶数。

现在智乃想要知道,如果他想要购买西瓜的重量和分别为k=1,2,3...Mk=1,2,3...M时,有多少种购买西瓜的方案,因为这些数字可能会很大,请输出方案数对109+7109+7取余数后的结果。

输入描述:

第一行输入两个整数N,M(0≤N≤103,1≤M≤103)N,M(0≤N≤103,1≤M≤103),分别表示西瓜的数目NN,以及查询的重量上限为MM。
若NN不为00,接下来一行NN个正偶数wi(2≤wi≤2×103)wi(2≤wi≤2×103)表示每个西瓜的重量。

输出描述:

输出一行MM个数字,分别表示购买西瓜的重量和为k=1,2,3...Mk=1,2,3...M时,有多少种购买西瓜的方案,因为这些数字可能会很大,请输出方案数对109+7109+7取余数后的结果。

示例1

输入

复制

3 6
8 2 4

输出

复制

1 2 1 3 2 3

比较裸的背包,dp[i, j]表示用前i个西瓜凑出j这个重量的方案数。需要注意的是dp数组第二维要开2e3,虽然m不超过1e3,但在代码中dp[i, w[i]] += 1;这一句涉及了wi,而wi可能达到2e3。转移方程见代码:

#include <iostream>
#include <map>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <queue>
#include <set>
#include <vector>
#define int long long
#define mod 1000000007
#define ll long long
#define pb push_back
#define pii pair<int,int>
using namespace std;
ll dp[1005][2005] = { 0 };
ll w[2005];
ll n, m;
signed main() {
	cin >> n >> m;
	for(ll i = 1; i <= n; i++) {
		cin >> w[i];
	}
	for(ll i = 1; i <= n; i++) {
		dp[i][w[i]] += 1;
		dp[i][w[i] / 2] += 1;
		for(int j = 1; j <= m; j++) {
			dp[i][j] = (dp[i - 1][j] + dp[i][j]) % mod;
			if(j - w[i] >= 0) dp[i][j] = (dp[i - 1][j - w[i]] + dp[i][j]) % mod;
			if(j - w[i] / 2 >= 0) dp[i][j] = (dp[i - 1][j - w[i] / 2] + dp[i][j]) % mod;
		}
	}
	for(int i = 1; i <= m; i++) {
		cout << dp[n][i] << " ";
	}
	return 0;
}

C. 智乃买瓜(another version)

链接:https://ac.nowcoder.com/acm/contest/23478/C
来源:牛客网

题目描述

本题是原*版*的另一个版本,简单来讲,本题是原版输入输出的倒置。

有一人前来买瓜。
“哥们儿,这瓜多少钱一斤呐”
“两块钱一斤”
“What's up,这瓜皮是金子做的,还是瓜粒子是金子做的”

智乃来到水果摊前买瓜,水果摊上贩卖着若干个不同的西瓜,第ii个西瓜的重量为wiwi。智乃对于每个瓜都可以选择买一个整瓜或者把瓜劈开买半个瓜,半个瓜的重量为wi22wi。

也就是说对于每个西瓜,智乃都有三种不同的决策:

  1. 购买一整个重量为wiwi的西瓜
  2. 把瓜劈开,购买半个重量为wi22wi的西瓜
  3. 不进行购买操作

为了简化题目,我们保证所有瓜的重量都是一个正偶数。

现在智乃知道,购买西瓜的重量和分别为k=1,2,3...Mk=1,2,3...M时,购买西瓜的方案的种类数对109+7109+7取余数后的结果。

她想要还原水果摊贩卖的这若干个不同的西瓜重量分别为多少,请你构造一个贩卖NN个不同西瓜的水果摊,其购买西瓜的重量和满足智乃的要求,当出现有多种符合题目描述的答案时,你只用输出任意一种。

我们保证输入的数据至少存在一个N≤103N≤103的合法解。

输入描述:

第一行输入一个正整数M(1≤M≤103)M(1≤M≤103),表示智乃所知购买西瓜质量和的上限。
接下来一行MM个整数,第ii个整数表示购买西瓜的重量和为ii时,购买西瓜的方案的种类数对109+7109+7取余数后的结果。

输出描述:

首先输出一个整数NN,西瓜的数目。要求你给出的NN大小范围在[0,103][0,103]之间
接下来一行NN个正偶数wiwi,表示每个每个西瓜的重量。要求你给出的wiwi大小范围在[2,2×103][2,2×103]之间,且wiwi为偶数。


输入数据保证,至少存在一组在输出范围内的合法解。

示例1

输入

复制

6
1 2 1 3 2 3

输出

复制

3
8 2 4

比赛时没有出思路,dp还是要多练~~~

首先容易知道2的个数是确定的。不放倒着考虑,在B题中dp[i, j]的方案数是怎么得到的,这里就怎么减去。思路就是在把一个个dp方案数变为0的过程中不断将使用的重量放到答案vector中。从前往后遍历dp数组,如果一个位置的值不为0,说明这些剩下的这个重量i对应的方案数只能由i*2这个西瓜/2来提供。此时就把一个i*2放入ans,然后更新后面的dp数组部分。

#include <iostream>
#include <map>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <queue>
#include <set>
#include <vector>
#define mod 1000000007
#define int long long
#define pb push_back
#define pii pair<int,int>
using namespace std;
int m, dp[1005], w[1005];
int c[2005] = { 0 };
int cnt = 0;
signed main() {
	cin >> m;
	for(int i = 1; i <= m; i++) {
		cin >> dp[i];
	}
	vector<int> ans;
	dp[0] = 1;//不要忘记
	for(int i = 1; i <= m; i++) {
		while(dp[i]) {
			ans.push_back(i * 2);
			for(int j = i; j <= m; j++) {//i==j时就是处理dp[i],剩下的方案数由dp[i]个i*2的瓜提供,因此dp[0]要设置为1,即每次都要减1
				dp[j] = (dp[j] - dp[j - i] + mod) % mod;
				if(j - i * 2 >= 0) dp[j] = (dp[j] - dp[j - i * 2] + mod) % mod;
			}
		}
	}
	cout << ans.size() << endl;
	for(auto x : ans) {
		cout << x << " ";
	}
	return 0;
}

D. 智乃的01串打乱

纯签,随便选两个01位置交换即可。

E. 智乃的数字积木

链接:https://ac.nowcoder.com/acm/contest/23478/E
来源:牛客网

题目描述

本题有对应的hard version,两者的区别仅在数据范围,保证easy version的测试用例集是hard version的子集。

智乃酱有NN块积木,每一块积木都有自己的颜色以及数字,这NN块积木颜色的范围从11到MM,数字的范围从00到99。
现在智乃酱把这些积木从左到右排成一排,这样积木看上去就形成了一个大整数,智乃觉得这个数字不够大,所以他决定交换一些积木使得这个大整数尽可能的大。

具体来讲,智乃可以在任意时刻无限次的交换相邻且同色的数字积木。
但是即使这样,智乃觉得这个数字还是不够大。

所以智乃酱拿出了她的油漆桶,她决定进行KK次操作,每次操作都选中两种颜色PP,QQ,然后将所有颜色为PP的积木染成颜色QQ。
当然,在染色结束后智乃酱也是可以交换相邻同色积木进行调整。

现在智乃想要知道,她进行KK次染色操作之前,以及每次染色后能够通过交换得到最大的正整数是多少,当然啦,这个大整数被允许包含前导零。
因为这个大整数很大,所以只要求你输出答案对109+7109+7取余数的结果即可。

输入描述:

第一行输入三个整数N,M,K(1≤N,M≤105,0≤K≤10)N,M,K(1≤N,M≤105,0≤K≤10)分别表示积木的数目,初始颜色的种类,以及智乃酱染色的次数。
接下来输入一个长度为NN的字符串,字符串仅由数字0−90−9组成。
接下来一行NN个正整数coli(1≤coli≤M)coli(1≤coli≤M)表示积木的颜色。
接下来KK行,每行输入两个正整数P,Q(1≤P,Q≤M)P,Q(1≤P,Q≤M)表示选中两种颜色PP,QQ,然后将所有颜色为PP的积木染成颜色QQ。

输出描述:

输出K+1K+1行,即她进行KK次染色操作之前,以及每次染色后能够通过交换得到最大的正整数对109+7109+7取余数的结果。

示例1

输入

复制

10 2 0
9586547120
1 2 1 2 1 1 1 1 1 1

输出

复制

586754147

示例2

输入

复制

10 2 1
9586547120
1 2 1 2 1 1 1 1 1 1
1 2

输出

复制

586754147
876554147

示例3

输入

复制

5 5 4
12345
1 2 3 4 5
3 2
2 5
4 5
5 1

输出

复制

12345
13245
13245
15432
54321

注意到k范围很小,因此每次染色直接暴力处理,然后对于同色的区间暴力排序,再暴力遍历计算字符串的值即可。

#include <iostream>
#include <map>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <queue>
#include <set>
#include <vector>
#define mod 1000000007
#define ll long long
#define pb push_back
#define pii pair<int,int>
using namespace std;
int n, m, k;
char s[100005];
int c[100005];
bool cmp(char a, char b) {
	return a > b;
}
int main() {
	cin >> n >> m >> k;
	c[n + 1] = -1;
	scanf("%s", s + 1);
	
	for(int i = 1; i <= n; i++) {
		cin >> c[i];
	}
	int lst = 1;
	for(int i = 2; i <= n + 1; i++) {
		if(c[i] != c[i - 1]) {
			sort(s + lst, s + (i - 1) + 1, cmp);
			lst = i;
		}
	}
	ll ans = 0;
	for(int i = 1; i <= n; i++) {
		ans = (ans * 10) % mod;
		ans = (ans + s[i] - '0') % mod;
	}
	cout << ans << endl;
	for(int i = 1; i <= k; i++) {
		int p, q;
		cin >> p >> q;
		for(int j = 1; j <= n; j++) {
			if(c[j] == p) c[j] = q;
		}
		int lst = 1;
		for(int j = 2; j <= n + 1; j++) {
			if(c[j] != c[j - 1]) {
				sort(s + lst, s + (j - 1) + 1, cmp);
				lst = j;
			}
		}
		ans = 0;
		for(int i = 1; i <= n; i++) {
			ans = (ans * 10) % mod;
			ans = (ans + s[i] - '0') % mod;
		}
		cout << ans << endl;
	}
	return 0;
}

G. 智乃的树旋转

链接:https://ac.nowcoder.com/acm/contest/23478/G
来源:牛客网

题目描述

本题有对应的hard version, *easy version有额外的限制条件*,保证easy version的测试用例集是hard version的子集。

树旋转是在二叉树中的一种子树调整操作, 每一次旋转并不影响对该二叉树进行中序遍历的结果。

树旋转通常应用于需要调整树的局部平衡性的场合。树旋转包括两个不同的方式,分别是左旋和右旋。 两种旋转呈镜像,而且互为逆操作。

img

如图所示,为树的左旋转和右旋转示意图。当AA节点位于BB节点的左子树时,可以进行以AA节点为旋转轴的右旋转,反之可以进行以BB节点为旋转轴的左旋转。

具体来讲

右旋转:

当节点AA位于节点BB的左孩子时,节点AA可作为旋转轴进行右旋转,该旋转操作涉及到结构改变的节点有44个。
我们记旋转前AA节点的右孩子为ββ节点,BB节点的父节点为XX节点(若BB节点就是整棵树的根节点,则无需做与XX节点相关的操作)。
则旋转后ββ节点由AA节点的右孩子变为BB节点的左孩子,XX节点的其中一个孩子节点由BB节点改变为AA节点,并且它们和XX节点的中序顺序不发生其他变化;也就是说原来BB节点是XX节点的右孩子,则旋转后变为AA节点替换BB节点成为XX节点新的右孩子,反之若BB节点初始是XX节点的左孩子,则旋转后AA节点替换BB节点成为XX节点新的左孩子。

左旋转:
当节点BB位于节点AA的右孩子时,节点BB可作为旋转轴进行左旋转,该旋转操作涉及到结构改变的节点有44个。
我们记旋转前BB节点的左孩子为ββ节点,AA节点的父节点为XX节点(若AA节点就是整棵树的根节点,则无需做与XX节点相关的操作)。
则旋转后ββ节点由BB节点的左孩子变为AA节点的右孩子,XX节点的其中一个孩子节点由AA节点改变为BB节点,并且它们和XX节点的中序顺序不发生其他变化;也就是说原来AA节点是XX节点的右孩子,则旋转后变为BB节点替换AA节点成为XX节点新的右孩子,反之若AA节点初始是XX节点的左孩子,则旋转后BB节点替换AA节点成为XX节点新的左孩子。

智乃最近学习了树旋转,树旋转的本质是二叉树旋转轴节点与其父节点父子关系的改变,从视觉效果上看起来好像整个树进行了“旋转”。

在实际的操作过程中,如果指定旋转轴,其实就没有所谓“左旋转”和“右旋转”的区别,当旋转轴确定时,将只有一种旋转方法,遵循以下规则。

  • 根节点无法作为旋转轴被选定。
  • 当旋转轴是其父节点的左子树时,旋转轴只能进行右旋转。
  • 当旋转轴是其父节点的右子树时,旋转轴只能进行左旋转。

现在智乃有一颗尺寸大小为NN二叉树,智乃对其做了一次旋转操作将其打乱,她想让你通过一系列树的旋转操作将其还原,要求你的操作次数不多于N2N2次。

输入描述:

第一行输入一个正整数N(1≤N≤103)N(1≤N≤103),表示二叉树的节点数目,节点从11到NN标号。


接下来NN行输入二叉树一开始的样子。
每行输入两个非负整数lch,rch(0≤lch,rch≤N)lch,rch(0≤lch,rch≤N)表示每个节点的左右子树。
当lchlch的值为00时,则表示该节点无左子树,当rchrch的值为00时,则表示该节点无右子树。



接下来NN行输入二叉树被打乱后的样子。
每行输入两个非负整数lch,rch(0≤lch,rch≤N)lch,rch(0≤lch,rch≤N)表示每个节点的左右子树。
当lchlch的值为00时,则表示该节点无左子树,当rchrch的值为00时,则表示该节点无右子树。


要求你将打乱后的二叉树通过一系列旋转操作还原

输出描述:

首先输出一个整数KK,表示你还原二叉树进行旋转的次数,要求你给出KK的范围在[0,N2][0,N2],接下来KK行,依次输出旋转操作的旋转轴。
由于旋转轴只能进行左旋转或者右旋转其中的一种,裁判程序将会自己判断当前需要进行的是左旋转还是右旋转。
注意:旋转过程中的根节点无法作为旋转轴进行旋转,如果你指定旋转过程中的根节点作为旋转轴,则裁判程序将直接给出WA的结果。


easy version额外限制条件,保证可以通过不多于一次树旋转的操作还原二叉树,即一定存在K≤1K≤1的解。

示例1

输入

复制

5
2 3
0 0
4 5
0 0
0 0
2 4
0 0
1 5
0 0
0 0

输出

复制

1
1

easy version比较简单,因为最多只旋转一次,因此旋转的只能是前后两棵树之间父子关系互换的两个点。

#include <iostream>
#include <map>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <queue>
#include <set>
#include <vector>
#define ll long long
#define pb push_back
#define pii pair<int,int>
using namespace std;
int n;
struct node {
	int ls, rs;
} n1[1005], n2[1005];
int fa1[1005], fa2[1005];
int main() {
	cin >> n;
	for(int i = 1; i <= n; i++) {
		int l, r;
		cin >> l >> r;
		n1[i].ls = l, n1[i].rs = r;
		fa1[l] = fa1[r] = i;
	}
	for(int i = 1; i <= n; i++) {
		int l, r;
		cin >> l >> r;
		n2[i].ls = l, n2[i].rs = r;
		fa2[l] = fa2[r] = i;
	}
	int p1 = 0, p2 = 0;
	for(int i = 1; i <= n; i++) {
		if(n1[i].ls != n2[i].ls || n1[i].rs != n2[i].rs) {
			if(!p1) p1 = i;
			else p2 = i;
		}
	}
	if(!p1 && !p2) {
		puts("0");
		return 0;
	}
	puts("1");
	int ans = 0;
	for(int i = 1; i <= n; i++) {
		for(int j = 1; j <= n; j++) {
			if(i != j && fa1[i] == j && fa2[j] == i) {
				ans = j;
				break;
			}
		}
	}
	cout << ans << endl;
	return 0;
}

I. 智乃的密码

链接:https://ac.nowcoder.com/acm/contest/23478/I
来源:牛客网

题目描述

智乃去注册账号,他发现网站的的密码必须符合以下几个条件

  • 密码是仅包含大小写英文字母、数字、特殊符号的字符串。
  • 密码的长度不少于LL个字符,并且不多于RR个字符。
  • 密码中应该至少包括①大写英文字母、②小写英文字母、③数字、④特殊符号这四类字符中的三种。

所谓特殊字符,是指非大小写字母、数字以及空格回车等不可见字符的可见字符,包括但不限于"~!@#$%^&*()_+"。

现在智乃有一个长度大小为NN的字符串SS,她想知道SS串中有多少个子串是一个符合条件的密码,请你帮助智乃统计符合条件的密码数目。

子串是指字符串中某一段连续的区间,例如对于字符串"abcde"来说,"abc","cde"都是它的子串,而"ace"不是它的子串。

输入描述:

第一行输入三个正整数N,L,R(1≤N≤105,1≤L≤R≤N)N,L,R(1≤N≤105,1≤L≤R≤N),表示SS串的长度,合法密码长度应该在LL到RR个字符之间。
接下来一行输入一个长度为NN的字符串SS,字符串仅包括①大写英文字母、②小写英文字母、③数字、④特殊符号四类字符。

输出描述:

仅一行一个整数,表示有多少子串是一个合法的密码。

示例1

输入

复制

10 6 8
asdfeg111*

输出

复制

3

说明

"eg111*","feg111*","dfeg111*"

这个题双指针或二分都可以做,比赛时写了半天错的双指针改不出来,没办法只能二分了...

二分时遍历每个可能的右端点,二分的是实际区间右端点到左端点的距离(因为距离小的时候满足,则距离大的时候一定满足,解满足单调性),判断区间是否合法可以用前缀和。举例来说,设有区间1 2 3 4 5 6,L = 3, R = 6, 如果[1 2 3 4]合法,那么[1 2 3 4 5]和[1 2 3 4 5 6]肯定都合法。

注意左端点不会超过1!一定要特别处理!代码比较抽象,简单参考一下吧~

#include <iostream>
#include <map>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <queue>
#include <set>
#include <vector>
#define int long long
#define ll long long
#define pb push_back
#define pii pair<int,int>
using namespace std;
int n, L, R;
char s[200005];
int sum[200005][4] = { 0 };
bool check(int mid, int i) {
	int a = sum[i][0] - sum[mid - 1][0];
	if(a) a = 1;
	int b = sum[i][1] - sum[mid - 1][1];
	if(b) b = 1;
	int c = sum[i][2] - sum[mid - 1][2];
	if(c) c = 1;
	int d = sum[i][3] - sum[mid - 1][3];
	if(d) d = 1;
	if(a + b + c + d >= 3) return 1;
	else return 0;
}
signed main() {
	cin >> n >> L >> R;
	scanf("%s", s + 1);
	int digit = 0, upper = 0, lower = 0, spe = 0;
	int lft = 1;
	int ans = 0;
	int cnt = 0;
	for(int i = 1; i <= n; i++) {
		for(int j = 0; j < 4; j++) {
			sum[i][j] = sum[i - 1][j];
		}
		if(s[i] >= '0' && s[i] <= '9') sum[i][0]++;
        else if(s[i] >= 'a' && s[i] <= 'z') sum[i][1]++;
        else if(s[i] >= 'A' && s[i] <= 'Z') sum[i][2]++;
        else sum[i][3]++;
        if(i < L) continue;
        int l = 0, r = min(R, i) - L, mid;
        while(l < r) {
        	mid = (l + r) >> 1;
        	if(check(i - (mid + L) + 1, i)) r = mid;
        	else l = mid + 1;
        }
        if(check(i - (l + L) + 1, i)) ans += (min(R, i) - (L + l) + 1);//
	}
	cout << ans;
	return 0;
}
// 10 3 5
// a1******1a

// 5 5 5
// a*111

L. 智乃的数据库

链接:https://ac.nowcoder.com/acm/contest/23478/L
来源:牛客网

题目描述

智乃最近在学习数据库的查询语言SQL。SQL (Structured Query Language:结构化查询语言) 是用于管理关系数据库管理系统(RDBMS)。 SQL 的范围包括数据插入、查询、更新和删除,数据库模式创建和修改,以及数据访问控制。

使用SQL,可以灵活的对数据库表进行操作,在数据库的查询语句中有"GROUP BY"这样一种关键字。

GROUP BY 语句用于结合聚合函数,根据一个或多个列对结果集进行分组。

例如数据库中储存了这样一个数据库表Table,执行带有"GROUP BY"关键字的查询语句。

id name val 1 chino 1 2 chino
2 3 kokoa
3 SELECT COUNT(*) FROM Table GROUP BY name;

SQL语句中COUNT表示聚合后每一个组中有多少条数据。

当执行上述的SQL查询语句后,其返回的结果如下

2 2 1第一行的2表示按照name字段进行分组聚合,一共可以分出2组。

第二行的两个整数表示每组中各有多少条数据。

当然了,"GROUP BY"关键字是可以选中多个列进行分组聚合的,只需要把这些字段用逗号隔开即可。

SELECT COUNT(*) FROM Table GROUP BY name,val;例如这样的SQL查询语句,执行后返回的结果如下

3 1 1 1现在智乃把这张数据库表导出给你,请你执行一个SELECT COUNT(*) FROM Table GROUP BY ...;的查询语句,请你把查询的结果告诉智乃。

为了简化问题,我们假设数据库的表由NN条记录以及MM个字段组成,且这些字段的类型均为int类型。

输入描述:

第一行输入两个正整数N,M(1≤N,M≤1000)N,M(1≤N,M≤1000),表示数据库表中有NN条记录以及MM个字段。


接下来一行输入MM个字符串Si(1≤∣Si∣≤50)Si(1≤∣Si∣≤50)表示每个字段的名称。


接下来NN行,每行MM列,输入一个二维表格datai,j(0≤datai,j≤109)datai,j(0≤datai,j≤109)表示数据库表中第ii条记录的第jj个字段的值。


接下来输入一行一个字符串SQL(1≤∣SQL∣≤5×104)SQL(1≤∣SQL∣≤5×104),表示查询语句,查询语句的格式为"SELECT    COUNT(∗)    FROM    Table    GROUP    BY    ...;""SELECTCOUNT(∗)FROMTableGROUPBY...;"。


其中"...""..."是若干个字段名称,保证是之前输入的MM个字段中的某些字段,且这若干个字段互不相同,字段与字段之间用一个逗号隔开。

输出描述:

第一行输出一个整数KK表示聚合后组的数目。
接下来一行输出KK个整数,表示每组中聚合的记录数目,整数与整数之间用空格隔开。


你可以按照你喜欢的顺序输出答案,裁判程序将忽略输出顺序的影响。

示例1

输入

复制

4 3
id name val
1 1 2
1 1 3
1 2 1
2 2 2
SELECT COUNT(*) FROM Table GROUP BY name,id;

输出

复制

3
1 2 1

模拟题。思路就是按这若干个字段进行排序,然后相邻的这若干个字段值相同的分到一组即可。

#include <iostream>
#include <map>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <queue>
#include <set>
#include <vector>
#define ll long long
#define pb push_back
#define pii pair<int,int>
using namespace std;
struct node {
	int data[1005];
} p[1005];
int rela[1005], cnt = 0;
bool cmp(node a, node b) {
	for(int i = 1; i <= cnt; i++) {
		if(a.data[rela[i]] == b.data[rela[i]]) continue;
		else return a.data[rela[i]] < b.data[rela[i]];
	}
	return a.data[rela[cnt]] < b.data[rela[cnt]];
}
int n, m;
string s[1005];
string sen;
map<string, int> mp;
int main() {
	cin >> n >> m;
	for(int i = 1; i <= m; i++) {
		cin >> s[i];
		mp[s[i]] = i;
	}
	for(int i = 1; i <= n; i++) {
		for(int j = 1; j <= m; j++) {
			cin >> p[i].data[j];
		}
	}
	getchar();
	getline(cin, sen);
	int pos = sen.find("BY");
	pos += 3;
	int lst = pos;
	for(int i = pos; i < sen.size(); i++) {
		if(sen[i] == ',' || sen[i] == ';') {
			string tmp = sen.substr(lst, i - lst);
			lst = i + 1;
			cnt++;
			rela[cnt] = mp[tmp];
		}
	}
	sort(p + 1, p + n + 1, cmp);
	int num = 1;
	vector<int> ans;
	for(int i = 2; i <= n + 1; i++) {
		bool diff = 0;
		for(int j = 1; j <= cnt; j++) {
			if(p[i].data[rela[j]] != p[i - 1].data[rela[j]]) {
				diff = 1;
				break;
			}
		}
		if(diff) {
			ans.push_back(num);
			num = 1;
		} else {
			num++;
		}
	}
	cout << ans.size() << endl;
	for(int i = 0; i < ans.size() - 1; i++) {
		cout << ans[i] << " ";
	}
	cout << ans[ans.size() - 1];
	return 0;
}

标签:include,int,旋转,牛客,2022,集训营,节点,dp,define
来源: https://www.cnblogs.com/lipoicyclic/p/15854172.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有