牛客练习赛16

比赛链接

A 字典序最大的子序列

题意就是题目意思,这里贪心的先把最大的字符选为第一个,接着是次大的。

然后这样会有个问题,子序列虽然不要求连续,但是要求按顺序,

所以可以设一个数组a[],a[i]表示i~n间最大的字符,这样就保证贪心不会出问题

#include<iostream>
#include<string>
#include<cstring>
#include<vector>
#include<map>
#include<algorithm>
#include<queue>
#include<set>
#include<cstdio>
#include<functional>
#include<iomanip>
#include<cmath>
#include<stack>
#include<iomanip>
#include<functional>
using namespace std;
const int maxn = 2 * (int)(1e5) + 100;
const int BN = 30;
const int inf = 0x3f3f3f3f;
const int mod = 1000000007;
const double eps = 1e-6;
typedef long long LL;
typedef unsigned long long ull;
char str[maxn];
char ans[maxn];
int maxp[maxn];
int main() {
    while (~scanf("%s", str)) {
        memset(maxp, 0, sizeof(maxp));
        int len = strlen(str);
        maxp[len - 1] = str[len - 1];
        for (int i = len - 2; i >= 0; i--) {
            int tmp = str[i];
            maxp[i] = max(maxp[i + 1], tmp);
        }
        int cnt = 0;
        memset(ans, 0, sizeof(ans));
        for (int i = 0; i < len; i++) {
            int tmp = str[i];
            if (tmp == maxp[i]) {
                ans[cnt++] = str[i];
            }
        }
        printf("%s\n", ans);
    }
    return 0;
}

B 漂亮的树

给出一些树的高度,问最少修改多少颗树能使这n颗树形成屋顶状(等腰三角形,差值为1)

笔者读的时候脑子抽了想到去算需要修最少的长度了

要尽量少修的话,显然就是找出去掉阶梯性质之后的最多有多少颗树是等高的,也就是把这个形状拍扁。

因为数值有点多所以map哈希吧

#include<iostream>
#include<string>
#include<cstring>
#include<vector>
#include<map>
#include<algorithm>
#include<queue>
#include<set>
#include<cstdio>
#include<functional>
#include<iomanip>
#include<cmath>
#include<stack>
#include<iomanip>
#include<functional>
using namespace std;
const int maxn = (int)(1e5) + 100;
const int BN = 30;
const int inf = 0x3f3f3f3f;
const int mod = 1000000007;
const double eps = 1e-6;
typedef long long LL;
typedef unsigned long long ull;
int a[maxn];
int main() {
	int n;
	while (~scanf("%d", &n)) {
		for (int i = 0; i < n; i++)
			scanf("%d", &a[i]);
		int m = (n + 1) / 2;
		for (int i = 0; i < m; i++)
			a[i] -= i;
		for (int i = m; i < n; i++)
			a[i] -= n - i - 1;
		map<int, int>mp;
		for (int i = 0; i < n; i++)
			mp[a[i]]++;
		int ans = 0;
		for (map<int, int>::iterator it = mp.begin(); it != mp.end(); ++it)
			ans = max(ans, it->second);
		printf("%d\n", n - ans);
	}
	return 0;
}

C 任意点

对于一些点,如果他们能通过规则连在一起,把他们归到一个点集,

对于两个不能连在一起的点集,根据规则显然只需要再加一个点就能把这两个点集连起来

所以先把所有点归并集合然后算集合数-1就是答案

这里用并查集吧

#include<iostream>
#include<string>
#include<cstring>
#include<vector>
#include<map>
#include<algorithm>
#include<queue>
#include<set>
#include<cstdio>
#include<functional>
#include<iomanip>
#include<cmath>
#include<stack>
#include<iomanip>
#include<functional>
using namespace std;
const int maxn = (int)(1e5) + 100;
const int BN = 30;
const int inf = 0x3f3f3f3f;
const int mod = 1000000007;
const double eps = 1e-6;
typedef long long LL;
typedef unsigned long long ull;
int pre[maxn];
struct nodes {
	bool visx[1111], visy[1111];
}a[111];
void init(int n) {
	for (int i = 0; i <= n; i++) {
		pre[i] = i;
		memset(a[i].visx, 0, sizeof(a[i].visx));
		memset(a[i].visy, 0, sizeof(a[i].visy));
	}
}
int find(int x) {
	if (x == pre[x]) return x;
	return pre[x] = find(pre[x]);
}
void unites(int x, int y) {
	x = find(x), y = find(y);
	if (x == y) return;
	else if (x > y) pre[x] = y;
	else pre[y] = x;
}
int main() {
	int n;
	while (~scanf("%d", &n)) {
		int x, y;
		init(n);
		for (int i = 0; i < n; i++) {
			scanf("%d%d", &x, &y);
			for (int j = 0; j < i; j++) {
				if (a[j].visx[x] || a[j].visy[y])
					unites(i, j);
			}
			a[i].visx[x] = a[i].visy[y] = 1;
		}
		int ans = 0;
		for (int i = 0; i < n; i++)
			if (i == find(i))
				ans++;
		printf("%d\n", ans - 1);
	}
	return 0;
}

D k进制数

待补

E 求值

把或的结果丢到set里不断算就行了,因为set内的元素不重复所以实际运算量不会很大

#include<iostream>
#include<string>
#include<cstring>
#include<vector>
#include<map>
#include<algorithm>
#include<queue>
#include<set>
#include<cstdio>
#include<functional>
#include<iomanip>
#include<cmath>
#include<stack>
#include<iomanip>
#include<functional>
using namespace std;
const int maxn = 4 * (int)(1e6) + 100;
const int BN = 30;
const int inf = 0x3f3f3f3f;
const int mod = 1000000007;
const double eps = 1e-6;
typedef long long LL;
typedef unsigned long long ull;
bool vis[maxn];
set<int> s[3];
int main(){
    int n, cur = 0, x;
    scanf("%d", &n);
    for (int i = 0; i < n; i++) {
        scanf("%d", &x);
        cur ^= 1;
        s[cur].clear();
        for (auto &it : s[cur ^ 1]) {
            int tmp = x | it;
            vis[tmp] = 1;
            s[cur].insert(tmp);
        }
        vis[x] = 1;
        s[cur].insert(x);
    }
    int ans = 0;
    for (int i = 0; i < maxn; i++)
        if (vis[i])
            ans++;
    printf("%d\n", ans);
    return 0;
}

F 选值

题目意思得 a[j]-a[i]<=d,转化过来就是a[i]>=a[j]-d

这样的话只要用二分查找到a[i],然后在i~j-1中选两个数就是符合题目的组合.

#include<iostream>
#include<string>
#include<cstring>
#include<vector>
#include<map>
#include<algorithm>
#include<queue>
#include<set>
#include<cstdio>
#include<functional>
#include<iomanip>
#include<cmath>
#include<stack>
#include<iomanip>
#include<functional>
using namespace std;
const int maxn = 2 * (int)(1e5) + 100;
const int BN = 30;
const int inf = 0x3f3f3f3f;
const int mod = 1000000007;
const double eps = 1e-6;
typedef long long LL;
typedef unsigned long long ull;
LL a[maxn];
int main() {
	int n;
	LL d;
	while (~scanf("%d%lld", &n, &d)) {
		for (int i = 0; i < n; i++)
			scanf("%lld", &a[i]);
		LL ans = 0;
		for (int i = n - 1; i >= 0; i--) {
			int pos = lower_bound(a, a + n, a[i] - d) - a;
			ans += LL(i - pos)*LL(i - pos - 1) / 2;
		}
		printf("%lld\n", ans);
	}
	return 0;
}

### 关于牛客网练习赛14 B题的解析 目前未找到直接针对牛客网练习赛14 B题的具体题解或比赛经验。然而,可以通过分析类似的题目以及常见的算法竞赛技巧来推测可能的解决方案。 #### 类似问题的解决思路 在算法竞赛中,B类题目通常涉及基础数据结构的应用或者简单的数学推导。以下是几种常见类型的处理方式: 1. **字符串操作** 若该题涉及到字符串处理,则可以利用C++中的`std::string`库函数[^2],例如查找子串、替换字符等操作。 2. **数组与序列** 对于数组或序列的操作,动态规划(Dynamic Programming, DP)是一种常用方法。通过定义状态转移方程,逐步解决问题。例如,在某些情况下,可以用滚动数组优化空间复杂度[^3]。 3. **图论模型** 如果题目描述中有提到节点之间的关系,可能是图论问题。此时可采用广度优先搜索(BFS)、深度优先搜索(DFS),甚至最短路径算法如Dijkstra或Floyd-Warshall来建模并求解[^1]。 4. **模拟与暴力枚举** 当面对简单逻辑判断或多步运算时,“模拟”成为一种有效手段。即按照题目给定规则一步步实现程序流程,虽然时间效率未必最优,但对于小规模输入非常适用[^5]。 下面提供一段伪代码框架供参考: ```cpp #include <iostream> using namespace std; int main(){ int testCase; cin >> testCase; while(testCase--){ // 输入处理... // 解决方案核心部分 // 输出结果 } } ``` #### 提升竞赛表现的经验分享 为了更好地准备此类赛事,建议采取以下策略: - 定期参与线上平台举办的各类比赛积累实战经历; - 复盘每次赛后官方发布的详解文档学习新知; - 加强基础知识巩固的同时拓宽思维边界尝试不同领域挑战项目; ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值