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题解相关推荐

  1. 牛客小白月赛19 题解

    牛客小白月赛19 A. 「水」滔天巨浪(思维) B. 「木」迷雾森林 (数字三角形模型) C. 「土」秘法地震(二维前缀和) F. 「水」悠悠碧波 (字符串) D. 「金」初心如金 (找规律) G. ...

  2. 牛客小白月赛27题解(部分)

    链接:https://ac.nowcoder.com/acm/contest/6874 来源:nowcoder 文章目录 A 巨木之森(树的直径) B 乐团派对(贪心) D 巅峰对决(线段树) E 使 ...

  3. 牛客小白月赛27 题解

    比赛时有点事,赛后补了一下题 A 巨木之森 题意就不复述了, 这题的核心内容就是树的直径. 观察下面的图可以发现,一个点遍历整棵树的路程就是 所有的边*2 - 从这个点出发所到的最远距离.根据树的直径 ...

  4. 牛客小白月赛65个人题解A-E

    1. 牛客小白月赛65 A. 牛牛去购物 题意:给定n元,购买价格为a元的篮球和价格为b的篮球,数量不定,要使得花掉的钱最多,也就是剩余的钱数最少,求这个值 (1 <= n, a, b < ...

  5. 牛客小白月赛60(A~C)题解

    原题地址:牛客小白月赛60_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ 题目A:小竹与妈妈 题意:输出(x-b)/a即可,没什么好说 代码: #include< ...

  6. 牛客小白月赛20 D.3的倍数

    牛客小白月赛20 D.3的倍数 题目描述 给你 n 个字符串,每个字符串最多包含 A - Z 这26个字母,Keven 现在取了一些字符串,发现每个字母出现的次数都是 3 的倍数,Keven 现在想要 ...

  7. F.孤独(牛客小白月赛39)

    F.孤独(牛客小白月赛39) 题意: 给定一棵树,寻找一个路径,将断掉所有与这个路径上的点相连的边,使得剩下的最大连通块的大小最小 题解: 这题有点印象,感觉做过,至少这个方法肯定遇到过 设dp[u] ...

  8. 牛客小白月赛24 J.建设道路

    牛客小白月赛24 J.建设道路 题目链接 题目描述 牛牛国有 nnn 个城市,编号为 1-n,第 iii 个城市有一个价值 aia_iai​ ,牛国的国王牛阔落特别喜欢在牛牛国旅游,并且他不想每次旅游 ...

  9. 牛客小白月赛27 B.乐团派对

    牛客小白月赛27 B.乐团派对 题目链接 题目描述 音乐是带给大家快乐的存在,而你的目标就是组建若干支乐队,让世界听到你们的演奏! 你目前有 nnn 位乐手,每位乐手只能进入一个乐队,但并不是每位乐手 ...

最新文章

  1. Workout Wednesday Redux (2017 Week 3)
  2. 【DIY】不到20元,升级热水器加装远程wifi控制功能,esp8266远程红外控制热水器启动...
  3. mysql读取表最后10条数据
  4. 【终极方法】Syntax error on tokens, delete these tokens
  5. id int primary key auto_increment是什么意思
  6. 小麦亩产一千八(jzoj 3461)
  7. php入门速成(2),PHP入门速成(1)
  8. linux获取bind返回值信息,v$sql_bind_capture 获取绑定变量信息
  9. RecyclerView实现滑动删除和拖拽功能
  10. python mpi多线程_使用 MPI for Python 并行化遗传算法
  11. Maven使用注解配置SQL映射器(@Results,@ResultMap)
  12. HDU1556 color the ball(前缀和)
  13. etcd upgrade
  14. 【MATLAB】QPSK调制与解调在MATLAB平台上的实现
  15. 多传感器融合方法综述
  16. 简单的省市区级联SQL脚本
  17. hive分隔符_hive默认分隔符
  18. python 下载qq群文件_利用多线程快速下载腾讯QQ群文件的方法
  19. 高一被清华姚班录取,高三委拒谷歌 offer,一个重度网瘾少年到理论计算机科学家的蜕变!......
  20. 安装程序无法创建新的系统分区或者无法识别

热门文章

  1. 【leetcode】把数字翻译成字符串 c++
  2. java对象数组排序_如何在Java中对对象数组进行排序?
  3. 修改mysql默认字符集为latin1_查看、设置与修改MySQL字符集
  4. 集装箱交接清单(CTNJJD)
  5. 过年了,你有多久没有放鞭炮了呢?
  6. jeecg-boot字典翻译改造(支持实体类详情查询自动翻译)
  7. python字典换行输出_python字典 更新
  8. python三目运算与匿名函数
  9. RERAN:安卓系统的定时和点击的录制和回放——(4)
  10. vue2的proxy代理解决跨域