牛客小白月赛30题解
A 黑白边
有n个点,m条边,每条边都分为黑边和白边,现在要选一些边,使得所有点都可以相互连通,要求用白边的条数最少。
看到所有的点都相互连通,就可以想到生成树,所以把所有的白边和黑边分类,先用黑色的边构造生成树,再用白色的,这样就可以使所用的白色的边最少。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <queue>
#include <stack>
#include <vector>
#include <set>
#include <map>
#include <list>
#include <deque>
#include <iomanip>
#include <iostream>
#include <algorithm>
using namespace std;#define IOS \ios::sync_with_stdio(false); \cin.tie(0); \cout.tie(0)
#define lowbit(a) (a & (-a))
#define ll long long
const int inf = 0x3f3f3f3f;
const int maxn = 2e5 + 10;
const int minn = 1e3 + 10;
const double PI = acos(-1.0);
#define mod 10000
#define eps 1e-10
/*------------------------------------------------------*/
struct edge
{int u, v, w;
} a[maxn];
int f[maxn];
int n, m;bool cmp(edge x, edge y)
{return x.w < y.w;
}int Find(int x)
{if (x == f[x])return x;return f[x] = Find(f[x]);
}void join(int x, int y)
{int fx = Find(x);int fy = Find(y);if (fx != fy)f[fx] = fy;
}void init()
{for (int i = 0; i <= n; i++)f[i] = i;
}int kruskal()
{int sum = 0, ans = 0;for (int i = 1; i <= m; i++){int fu = Find(a[i].u);int fv = Find(a[i].v);if (fu != fv){sum++;join(a[i].u, a[i].v);if (a[i].w == 1)ans++;}if (sum == n - 1)break;}if (sum == n - 1) return ans;return -1;
}int main()
{scanf("%d %d",&n,&m);init();for (int i = 1; i <= m; i++)scanf("%d %d %d", &a[i].u, &a[i].v, &a[i].w);sort(a + 1, a + m + 1, cmp);int ans=kruskal();printf("%d\n",ans);return 0;
}
B、最好的宝石
有n个宝石,第i个宝石的价值为w[i],然后有m个操作:
第一种是Change x y 把第x个宝石的价值改成 y ;
第二种是 Ask l r 询问区间[l,r]内宝石的最大价值,和最大价值的宝石有多少个。
线段树维护区间最大值,特殊的是这题还需要输出这段区间内最大值的个数,其实就是在pushup的时候判断一下,取左右两个子节点的最大值,然后让其父节点的值更新为这个最大值,并且把个数更新一下就可以了。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <queue>
#include <stack>
#include <vector>
#include <set>
#include <map>
#include <list>
#include <deque>
#include <iomanip>
#include <iostream>
#include <algorithm>
#include <bits/stdc++.h>
using namespace std;#define IOS \ios::sync_with_stdio(false); \cin.tie(0); \cout.tie(0)
#define lowbit(a) (a & (-a))
#define ll long long
const int inf = 0x3f3f3f3f;
const int maxn = 2e5 + 10;
const int minn = 1e3 + 10;
const double PI = acos(-1.0);
#define mod 10000
#define eps 1e-10
/*------------------------------------------------------*/
struct node
{int l, r, w, sum;
} Tree[maxn << 2];
int a[maxn << 2];
int n, m, maxw, maxsum;
string s;void pushup(int rt)
{Tree[rt].w = max(Tree[rt << 1].w, Tree[rt << 1 | 1].w);Tree[rt].sum = 0;if (Tree[rt].w == Tree[rt << 1].w)Tree[rt].sum += Tree[rt << 1].sum;if (Tree[rt].w == Tree[rt << 1 | 1].w)Tree[rt].sum += Tree[rt << 1 | 1].sum;
}void build(int rt, int l, int r)
{Tree[rt] = {l, r, a[l], 1};if (l == r)return;else{int mid = (l + r) >> 1;build(rt << 1, l, mid);build(rt << 1 | 1, mid + 1, r);pushup(rt);}
}void query(int rt, int l, int r)
{if (Tree[rt].l >= l && Tree[rt].r <= r){if (Tree[rt].w == maxw)maxsum += Tree[rt].sum;if (Tree[rt].w > maxw){maxw = Tree[rt].w;maxsum = Tree[rt].sum;}return;}int mid = (Tree[rt].l + Tree[rt].r) >> 1;if (l <= mid)query(rt << 1, l, r);if (r > mid)query(rt << 1 | 1, l, r);
}void update(int rt, int x, int k)
{if (Tree[rt].l == x && Tree[rt].r == x){Tree[rt].sum = 1;Tree[rt].w = k;return;}else{int mid = (Tree[rt].l + Tree[rt].r) >> 1;if (x <= mid)update(rt << 1, x, k);elseupdate(rt << 1 | 1, x, k);pushup(rt);}
}int main()
{cin >> n >> m;for (int i = 1; i <= n; i++)cin >> a[i];build(1, 1, n);while (m--){maxw = 0;maxsum = 0;int x, y;cin >> s >> x >> y;if (s == "Change")update(1, x, y);else{query(1, x, y);cout << maxw << " " << maxsum << endl;}}return 0;
}
C、滑板上楼梯
有n个台阶,每次可以选择跳一阶或者三阶,但是不能连续选择跳三阶的,要求刚好到第n阶需要最少多少次。
因为要求最少次数,所以能选跳三阶的就选跳三阶的,因为不能连续跳三阶,所以每次选完三阶,就选一次跳一阶的,所以最后的答案就是(n/4)*2+n%4
,然后余数为3的时候再判断一下就可以了。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <queue>
#include <stack>
#include <vector>
#include <set>
#include <map>
#include <list>
#include <deque>
#include <iomanip>
#include <iostream>
#include <algorithm>
using namespace std;#define IOS \ios::sync_with_stdio(false); \cin.tie(0); \cout.tie(0)
#define lowbit(a) (a & (-a))
#define ll long long
const int inf = 0x3f3f3f3f;
const int maxn = 2e5 + 10;
const int minn = 1e3 + 10;
const double PI = acos(-1.0);
#define mod 1000000007
#define eps 1e-10
/*------------------------------------------------------*/
int main()
{ll n;cin >> n;if (n % 4 == 0)cout << n / 4 * 2 << endl;else if (n % 4 == 3)cout << n / 4 * 2 + 1 << endl;elsecout << n / 4 * 2 + n % 4 << endl;return 0;
}
D、GCD
有一个包含1-n所有数的集合S,要找一个最小的k,使得从S中任意找一个元素个数为k的子集T,T中都存在两个数u,v,且GCD(u,v)>1。
GCD(u,v)>1就说明这两个数不互质,因为题目要求是任意找一个子集都要满足,所以要找的k其实就是1-n内所有质数的个数+2(加2是因为1也要放进去,还有一个就是要加进去,才可以存在两个数不互质)。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <queue>
#include <stack>
#include <vector>
#include <set>
#include <map>
#include <list>
#include <deque>
#include <iomanip>
#include <iostream>
#include <algorithm>
#include <bits/stdc++.h>
using namespace std;#define IOS \ios::sync_with_stdio(false); \cin.tie(0); \cout.tie(0)
#define lowbit(a) (a & (-a))
#define ll long long
const int inf = 0x3f3f3f3f;
const int maxn = 1e5 + 10;
const int minn = 1e3 + 10;
const double PI = acos(-1.0);
#define mod 10000
#define eps 1e-10
/*------------------------------------------------------*/int is_prime(int x)
{for (int i = 2; i * i <= x; i++)if (x % i == 0)return 0;return 1;
}int main()
{int n;scanf("%d", &n);if (n < 4)printf("-1\n");else{int ans = 0;for (int i = 2; i <= n; i++)if (is_prime(i))ans++;printf("%d\n", ans + 2);}return 0;
}
E、牛牛的加法
给两个数a,b,求这两个数的和,不需要进位。
倒过来每一位加起来不要进位,模拟一下就可以。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <queue>
#include <stack>
#include <vector>
#include <set>
#include <map>
#include <list>
#include <deque>
#include <iomanip>
#include <iostream>
#include <algorithm>
using namespace std;#define IOS \ios::sync_with_stdio(false); \cin.tie(0); \cout.tie(0)
#define lowbit(a) (a & (-a))
#define ll long long
const int inf = 0x3f3f3f3f;
const int maxn = 2e5 + 10;
const int minn = 1e3 + 10;
const double PI = acos(-1.0);
#define mod 1000000007
#define eps 1e-10
/*------------------------------------------------------*/char a[maxn], b[maxn];
int aa[maxn], bb[maxn], ans[maxn];int main()
{cin >> a >> b;int la = strlen(a);int lb = strlen(b);int lc = max(la, lb);int tmp=0;for (int i = la - 1; i >= 0; i--)aa[tmp++] = a[i] - '0';tmp=0;for (int i = lb - 1; i >= 0; i--)bb[tmp++] = b[i] - '0';for (int i = 0; i < lc; i++){int cnt = aa[i] + bb[i];if (cnt < 10)ans[i] = cnt;elseans[i] = cnt - 10;}int flag = 0;for (int i = lc-1; i >=0; i--){if (ans[i] != 0)flag = 1;if (flag)cout << ans[i];}if (flag == 0)cout << ans[lc - 1];cout << endl;return 0;
}
F、石子合并
有n堆石子,每堆石子有a[i]个,每次可以选择相邻的两堆石子,拿走少的那堆,得到的价值是这两堆石子的个数之和,要求怎么拿能得到最大的价值。(注意,如果拿走了第 i 堆石子, 那么第 i-1 堆和第 i+1 堆 就会相邻。)
因为每次选择相邻的两堆,然后拿走少的那堆,价值为两堆的和,所以不管怎么拿,石子数量最多的那堆肯定能留到最后,贪心思想,要使得到的价值最大,可以每次都选石子数量最多那堆和它相邻的,这样能保证价值最大。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <queue>
#include <stack>
#include <vector>
#include <set>
#include <map>
#include <list>
#include <deque>
#include <iomanip>
#include <iostream>
#include <algorithm>
using namespace std;#define IOS \ios::sync_with_stdio(false); \cin.tie(0); \cout.tie(0)
#define lowbit(a) (a & (-a))
#define ll long long
const int inf = 0x3f3f3f3f;
const int maxn = 2e5 + 10;
const int minn = 1e3 + 10;
const double PI = acos(-1.0);
#define mod 10000
#define eps 1e-10
/*------------------------------------------------------*/
ll a[maxn];int main()
{int n;cin >> n;ll maxx = 0,sum = 0;for (int i = 0; i < n; i++){cin >> a[i];maxx = max(maxx, a[i]);sum += a[i];}sum -= maxx;sum += (n - 1) * maxx;cout << sum << endl;return 0;
}
G、滑板比赛
两个人进行滑板比赛,牛牛会n个动作,每个动作的华丽值为a[i],牛妹会m个动作,每个动作的华丽值为b[i],牛牛已经知道牛妹比赛使用动作的顺序,他想知道自己怎么安排动作顺序,才能赢得更多比赛的次数。
因为已经知道牛妹的动作顺序,然后可以随意安排牛牛的动作顺序,所以直接把两个数组都从大到小排序一下,然后判断牛牛能赢多少次就可以了。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <queue>
#include <stack>
#include <vector>
#include <set>
#include <map>
#include <list>
#include <deque>
#include <iomanip>
#include <iostream>
#include <algorithm>
using namespace std;#define IOS \ios::sync_with_stdio(false); \cin.tie(0); \cout.tie(0)
#define lowbit(a) (a & (-a))
#define ll long long
const int inf = 0x3f3f3f3f;
const int maxn = 2e5 + 10;
const int minn = 1e3 + 10;
const double PI = acos(-1.0);
#define mod 10000
#define eps 1e-10
/*------------------------------------------------------*/
int a[maxn], b[maxn];int main()
{int n, m;scanf("%d %d", &n, &m);for (int i = 0; i < n; i++)scanf("%d", &a[i]);for (int i = 0; i < m; i++)scanf("%d", &b[i]);sort(b, b + m, greater<int>());sort(a, a + n, greater<int>());int i = 0, j = 0, ans = 0;while (i < n && j < m){if (a[i] > b[j]){ans++;i++;j++;}else{j++;}}printf("%d\n", ans);return 0;
}
H、第k小
有一个长度为n的数组,要找数组中第k小的数,然后有两种操作,第一种是给数组中加一个元素x,第二种是查询第k小的数。
用优先队列实现,把数组里的数都放到优先队列里,让队列从小到大排,每次加一个数的时候就把这个数放进去,查询的时候,就让队列中的前k-1个数出队,这时候队首元素就是第k小的数。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <queue>
#include <stack>
#include <vector>
#include <set>
#include <map>
#include <list>
#include <deque>
#include <iomanip>
#include <iostream>
#include <algorithm>
#include <bits/stdc++.h>
using namespace std;#define IOS \ios::sync_with_stdio(false); \cin.tie(0); \cout.tie(0)
#define lowbit(a) (a & (-a))
#define ll long long
const int inf = 0x3f3f3f3f;
const int maxn = 1e5 + 10;
const int minn = 1e3 + 10;
const double PI = acos(-1.0);
#define mod 10000
#define eps 1e-10
/*------------------------------------------------------*/
struct node
{int x;bool operator<(const node &a){return x < a.x;}
};priority_queue<int> q;int main()
{int n, m, k;scanf("%d%d%d", &n, &m, &k);for (int i = 0; i < n; i++){int x;scanf("%d", &x);q.push(x);}while (m--){int d;scanf("%d", &d);if (d == 1){int x;scanf("%d", &x);q.push(x);}else{if (q.size() < k)printf("-1\n");else{while (q.size() > k){q.pop();}printf("%d\n", q.top());}}}return 0;
}
I、区间异或和
有一个长度为 n 的数组 a[i] , 有 m 次询问, 每次询问给一个值 x , 找出一个最短的区间, 使得这个区间的异或和 ≥ x , 输出区间长度。
因为n只有3000,所以先预处理每个长度区间的异或的最大值,然后排序,二分查找。(好像直接暴力找也可以过)
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <queue>
#include <stack>
#include <vector>
#include <set>
#include <map>
#include <list>
#include <deque>
#include <iomanip>
#include <iostream>
#include <algorithm>
#include <bits/stdc++.h>
using namespace std;#define IOS \ios::sync_with_stdio(false); \cin.tie(0); \cout.tie(0)
#define lowbit(a) (a & (-a))
#define ll long long
const int inf = 0x3f3f3f3f;
const int maxn = 1e4 + 10;
const int minn = 1e3 + 10;
const double PI = acos(-1.0);
#define mod 10000
#define eps 1e-10
/*------------------------------------------------------*/
int a[maxn], sum[maxn], val[maxn], ans[maxn];vector<pair<int, int>> vec;
bool cmp(pair<int, int> x, pair<int, int> y)
{return x.first < y.first;
}
int main()
{int n, m;scanf("%d %d", &n, &m);for (int i = 1; i <= n; i++){scanf("%d", &a[i]);sum[i] = sum[i - 1] ^ a[i];}for (int i = 1; i <= n; i++)for (int j = i; j <= n; j++)val[j - i + 1] = max(val[j - i + 1], sum[i - 1] ^ sum[j]);for (int i = 1; i <= n; i++)vec.push_back({val[i], i});sort(vec.begin(), vec.end(), cmp);ans[n + 1] = inf;for (int i = n; i >= 1; i--)ans[i] = min(ans[i + 1], vec[i - 1].second);while (m--){int x;scanf("%d", &x);int cnt = lower_bound(vec.begin(), vec.end(), make_pair(x, 0)) - vec.begin() + 1;if (cnt > vec.size()){printf("-1\n");continue;}printf("%d\n", ans[cnt]);}return 0;
}
J、小游戏
有一个长度为n的数组a[i],每次可以拿走一个数,如果拿了第i个数,这个数为x,那么x+1 和 x-1 (如果有 a[j] = x+1 或 a[j] = x-1 存在) 就会变得不可拿(但是有 a[j] = x 的话可以继续拿这个 x ),求最大分数。
先预处理每个数出现的次数,然后dp一下每个数要不要选就好了。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <queue>
#include <stack>
#include <vector>
#include <set>
#include <map>
#include <list>
#include <deque>
#include <iomanip>
#include <iostream>
#include <algorithm>
#include <bits/stdc++.h>
using namespace std;#define IOS \ios::sync_with_stdio(false); \cin.tie(0); \cout.tie(0)
#define lowbit(a) (a & (-a))
#define ll long long
const int inf = 0x3f3f3f3f;
const int maxn = 2e5 + 10;
const int minn = 1e3 + 10;
const double PI = acos(-1.0);
#define mod 10000
#define eps 1e-10
/*------------------------------------------------------*/
int a[maxn], vis[maxn];
ll dp[maxn];int main()
{int n;scanf("%d", &n);for (int i = 1; i <= n; i++){scanf("%d", &a[i]);vis[a[i]]++;}int maxx = maxn - 10;dp[1] = vis[1];for (int i = 2; i <= maxx; i++)dp[i] = max(dp[i - 1], dp[i - 2] + vis[i] * i);printf("%lld\n", dp[maxx]);return 0;
}
牛客小白月赛30题解相关推荐
- 牛客小白月赛19 题解
牛客小白月赛19 A. 「水」滔天巨浪(思维) B. 「木」迷雾森林 (数字三角形模型) C. 「土」秘法地震(二维前缀和) F. 「水」悠悠碧波 (字符串) D. 「金」初心如金 (找规律) G. ...
- 牛客小白月赛27题解(部分)
链接:https://ac.nowcoder.com/acm/contest/6874 来源:nowcoder 文章目录 A 巨木之森(树的直径) B 乐团派对(贪心) D 巅峰对决(线段树) E 使 ...
- 牛客小白月赛27 题解
比赛时有点事,赛后补了一下题 A 巨木之森 题意就不复述了, 这题的核心内容就是树的直径. 观察下面的图可以发现,一个点遍历整棵树的路程就是 所有的边*2 - 从这个点出发所到的最远距离.根据树的直径 ...
- 牛客小白月赛65个人题解A-E
1. 牛客小白月赛65 A. 牛牛去购物 题意:给定n元,购买价格为a元的篮球和价格为b的篮球,数量不定,要使得花掉的钱最多,也就是剩余的钱数最少,求这个值 (1 <= n, a, b < ...
- 牛客小白月赛60(A~C)题解
原题地址:牛客小白月赛60_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ 题目A:小竹与妈妈 题意:输出(x-b)/a即可,没什么好说 代码: #include< ...
- 牛客小白月赛20 D.3的倍数
牛客小白月赛20 D.3的倍数 题目描述 给你 n 个字符串,每个字符串最多包含 A - Z 这26个字母,Keven 现在取了一些字符串,发现每个字母出现的次数都是 3 的倍数,Keven 现在想要 ...
- F.孤独(牛客小白月赛39)
F.孤独(牛客小白月赛39) 题意: 给定一棵树,寻找一个路径,将断掉所有与这个路径上的点相连的边,使得剩下的最大连通块的大小最小 题解: 这题有点印象,感觉做过,至少这个方法肯定遇到过 设dp[u] ...
- 牛客小白月赛24 J.建设道路
牛客小白月赛24 J.建设道路 题目链接 题目描述 牛牛国有 nnn 个城市,编号为 1-n,第 iii 个城市有一个价值 aia_iai ,牛国的国王牛阔落特别喜欢在牛牛国旅游,并且他不想每次旅游 ...
- 牛客小白月赛27 B.乐团派对
牛客小白月赛27 B.乐团派对 题目链接 题目描述 音乐是带给大家快乐的存在,而你的目标就是组建若干支乐队,让世界听到你们的演奏! 你目前有 nnn 位乐手,每位乐手只能进入一个乐队,但并不是每位乐手 ...
最新文章
- Workout Wednesday Redux (2017 Week 3)
- 【DIY】不到20元,升级热水器加装远程wifi控制功能,esp8266远程红外控制热水器启动...
- mysql读取表最后10条数据
- 【终极方法】Syntax error on tokens, delete these tokens
- id int primary key auto_increment是什么意思
- 小麦亩产一千八(jzoj 3461)
- php入门速成(2),PHP入门速成(1)
- linux获取bind返回值信息,v$sql_bind_capture 获取绑定变量信息
- RecyclerView实现滑动删除和拖拽功能
- python mpi多线程_使用 MPI for Python 并行化遗传算法
- Maven使用注解配置SQL映射器(@Results,@ResultMap)
- HDU1556 color the ball(前缀和)
- etcd upgrade
- 【MATLAB】QPSK调制与解调在MATLAB平台上的实现
- 多传感器融合方法综述
- 简单的省市区级联SQL脚本
- hive分隔符_hive默认分隔符
- python 下载qq群文件_利用多线程快速下载腾讯QQ群文件的方法
- 高一被清华姚班录取,高三委拒谷歌 offer,一个重度网瘾少年到理论计算机科学家的蜕变!......
- 安装程序无法创建新的系统分区或者无法识别