2024ICPC网络赛第一场题解(部分)

news/2024/11/16 15:30:50/文章来源:https://www.cnblogs.com/TJUHuangTao/p/18415578

这一场基本纯挂件,给队友翻译翻译题面,帮队友打打板子了,可惜最后40sL题冲了一个 \(O(\frac{n^3}{w})\) 的bitset最后wa了,所以下面的题解我也只能看着队友代码说说大概,主要参考一下代码吧。

A

题意

给出32个队伍的能力值,和比赛的规则,其中中国队是第一个队伍,问所有分组的情况下,中国队的最好可能成绩是什么。
签到,首先因为32个队能力值都不同,所以只需要看中国队的能力值排名,就决定了最终的答案。具体的话队友应该是手玩了各个情况,写了一堆if else过的。

代码

点击查看代码
#include <bits/stdc++.h>
#define int long long
#define pb push_back
#define pii pair<int, int>
using namespace std;
bool debug = 1;
#define dbg(x)                                                   \if (debug)                                                   \cerr << BRIGHT_CYAN << #x << COLOR_RESET << " = " << (x) \<< NORMAL_FAINT << COLOR_RESET << endl;
const string COLOR_RESET = "\033[0m", BRIGHT_CYAN = "\033[1;36m",NORMAL_FAINT = "\033[0;2m";void solve() {int a[32];int de = 0;for (int i = 0; i < 32; i++) {cin >> a[i];if (a[i] <= a[0])de++;}if (de == 32) {cout << 1;} else if (de >= 28) {cout << 2;} else if (de >= 14) {cout << 4;} else if (de >= 7) {cout << 8;} else if (de >= 3) {cout << 16;} elsecout << 32;cout << endl;
}signed main() {ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int t = 1;cin >> t;while (t--)solve();return 0;
}//__builtin_popcountll()
// cout<<fixed<<setprecision(2);

C

题意

给定 \(n\) 个限制 \((l_i, r_i)\), 问长度为 \(n\) 的全排列中,且满足第 \(i\) 个数位于区间 \((l_i, r_i)\)内的排列数个数的奇偶性。

首先题目既然只问的奇偶性,就说明不太可能暴力求出来真正的总个数。然后队友画画图,最后猜了个结论,对每个限制 \((l_i, r_i)\) 建一条边 \(l-1, r\),最后看建出来的图是不是一棵树。瞪眼法秒了,具体原理还不太清楚,看群里别人说好像跟什么满秩,线性代数什么的知识有关。

代码

点击查看代码
#include<bits/stdc++.h>
#define int long long 
#define pb push_back
#define pii pair<int,int>
using namespace std;
bool debug = 1;
#define dbg(x) if(debug) cerr<<BRIGHT_CYAN<<#x<<COLOR_RESET<<" = "<<(x)<<NORMAL_FAINT<<COLOR_RESET<<endl;
const string COLOR_RESET = "\033[0m", BRIGHT_CYAN = "\033[1;36m", NORMAL_FAINT = "\033[0;2m";void solve(){int n;cin >> n;int sum = 0;vector<int> a[n + 1]{};vector<int> vis(n+1);for (int i = 1; i <= n;i++){int u, v;cin >> u >> v;u--;a[u].pb(v);a[v].pb(u);}function<void(int)> dfs = [&](int u) {if(vis[u]==0)sum++, vis[u] = 1;for(auto p:a[u]){if(vis[p]==0)dfs(p);}};dfs(0);if(sum==n+1)cout << 1;elsecout << 0;cout << '\n';
}signed main(){ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int t = 1;cin>>t;while(t--)solve();return 0;
}//__builtin_popcountll()
// cout<<fixed<<setprecision(2);

F

题意

给一个数组,每次操作选择一个区间,满足区间内的数不能完全相同,然后将区间里的数全都改为区间最大值,问最多能操作多少次

首先容易去考虑,对于每个数,利用单调栈求出它作为区间内唯一最大值的范围,那么操作的时候,就可以从小到大依次操作这些区间,然后基本上就做完了,具体的式子可能还得推推,看代码似乎就是把这样的区间长度加起来。

代码

点击查看代码
#include<bits/stdc++.h>
#define int long long 
#define pb push_back
#define pii pair<int,int>
using namespace std;
bool debug = 1;
#define dbg(x) if(debug) cerr<<BRIGHT_CYAN<<#x<<COLOR_RESET<<" = "<<(x)<<NORMAL_FAINT<<COLOR_RESET<<endl;
const string COLOR_RESET = "\033[0m", BRIGHT_CYAN = "\033[1;36m", NORMAL_FAINT = "\033[0;2m";const int N = 2e5 + 999;
int n, a[N], stk[N], top, l[N], r[N];
void solve(){cin >> n;for (int i = 1; i <= n; i++)cin >> a[i];stk[top = 0] = 0;for (int i = 1; i <= n; i++){while(top && a[i] > a[stk[top]])top--;l[i] = stk[top] + 1;stk[++top] = i;}stk[top = 0] = n + 1;a[n + 1] = 0;for (int i = n; i >= 1; i--){while(top && a[i] > a[stk[top]])top--;r[i] = stk[top] - 1;if(a[r[i] + 1] == a[i])r[i] = i;stk[++top] = i;}int ans = 0;for (int i = 1; i <= n; i++)ans += r[i] - l[i];cout << ans << '\n';
}
signed main(){ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int t = 1;cin>>t;while(t--)solve();return 0;
}//__builtin_popcountll()
// cout<<fixed<<setprecision(2);

G

题意

给一个长度 \(2\times 10^3\) 的数组 \(a[n]\), 可以得到一个 \(n \times n\) 的二维数组 \(b[i][j]\), 表示数组\(a\) 在区间 \([i, j]\) 的中位数。再由数组 \(b[n][n]\) 得到一个二维数组 \(c[i][j]\) 表示数组 \(b[n][n]\)\((i, i) to (j, j)\) 这个矩形范围内的中位数。最后问你数组 \(c[n][n]\) 的中位数是多少。

首先看到中位数很容易去考虑二分答案后,转01矩阵。那么这题同理,首先因为 \(n\) 很小,最终答案肯定是数组 \(a[n]\) 的某个数,只要在这些数里面二分,然后数组 \(b[i][j]\) 直接 \(O(n^2)\) 的枚举,用前缀和暴力算。对数组 \(b[n][n]\) 再去二维前缀和, \(O(n^2)\) 地暴力求出数组 \(c\),最后判断数组 \(c[n][n]\) 里1的个数。详见代码

代码

点击查看代码
#include<bits/stdc++.h>
#define int long long 
#define pb push_back
#define pii pair<int,int>
using namespace std;
bool debug = 1;
#define dbg(x) if(debug) cerr<<BRIGHT_CYAN<<#x<<COLOR_RESET<<" = "<<(x)<<NORMAL_FAINT<<COLOR_RESET<<endl;
const string COLOR_RESET = "\033[0m", BRIGHT_CYAN = "\033[1;36m", NORMAL_FAINT = "\033[0;2m";const int N = 2033;int n, a[N], rk[N], s[N], b[N][N], c[N][N], sb[N][N];bool check(int x){for (int i = 1; i <= n; i++){s[i] = s[i - 1] + (a[i] > x);}int cnt = 0;for (int i = 1; i <= n; i++)for (int j = i; j <= n; j++)b[i][j] = !(j - i + 1 - s[j] + s[i - 1] >= (j - i + 2) / 2);/*for (int i = 1; i <= n; i++)for (int j = 1; j <= n; j++)cout << b[i][j] << " \n"[j == n];*/for (int i = 1; i <= n; i++)for (int j = 1; j <= n; j++)sb[i][j] = sb[i - 1][j] + sb[i][j - 1] + b[i][j] - sb[i - 1][j - 1];for (int i = 1; i <= n; i++)for (int j = i; j <= n; j++){c[i][j] = (sb[j][j] - sb[i - 1][j] - sb[j][i - 1] + sb[i - 1][i - 1]);int sz = (j - i + 2) * (j - i + 1) / 2;if(sz - c[i][j] >= (sz + 1) / 2)cnt++;}return cnt >= (n * (n + 1) / 2 + 1) / 2;
}
void solve(){cin >> n;for (int i = 1; i <= n; i++)cin >> a[i], rk[i] = a[i];sort(rk + 1, rk + n + 1);int l = 1, r = n, mid;while(l < r){mid = (l + r) >> 1;if(check(rk[mid]))r = mid;elsel = mid + 1;}cout << rk[l];
}signed main(){ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int t = 1;while(t--)solve();return 0;
}//__builtin_popcountll()
// cout<<fixed<<setprecision(2);

H

题意

括号序列长度为 \(2 * n\) ,每个位置给定了颜色 \(col[i]\), 并且有一个价值 \(val[i]\), 括号序列的价值定义为左括号所在位置的价值和。一个括号序列合法,需要括号序列本身是正则匹配的,还对每种颜色要求了,\(n\) 个左括号中对应颜色的数量至少达到 \(cnt[i]\) 个。问所有合法的括号序列的最大价值是多少。数据范围比较小, \(n \leq 100\) 左右。

括号序列会想起来很久之前牛客的一次练习赛(https://ac.nowcoder.com/acm/contest/75768/F)里面有跟网络流结合起来判合法括号,看到数据范围挺小,就让队友想想能不能用网络流,最大流保证括号合法,费用流求最大价值。然后队友比划比划后想出来建模了,把左括号数量下界的限制,转化为右括号的数量上界限制,先把所有价值加起来,然后匹配上一个右括号,相当于去掉所在位置的价值,所以最小费用就可以让最后剩的价值最大。具体建模可以看看代码里面,而且有一个wa点,就是如果给的左括号数量本身不合法,可能建模会建出来负的边权,需要特判掉-1.

代码

点击查看代码
#include<bits/stdc++.h>
#define int long long 
#define pb push_back
#define pii pair<int,int>
using namespace std;
bool debug = 1;
#define dbg(x) if(debug) cerr<<BRIGHT_CYAN<<#x<<COLOR_RESET<<" = "<<(x)<<NORMAL_FAINT<<COLOR_RESET<<endl;
const string COLOR_RESET = "\033[0m", BRIGHT_CYAN = "\033[1;36m", NORMAL_FAINT = "\033[0;2m";
const int N = 1009;
int n, m, dist[N], head[N], flow[N], vis[N], S, T, tot, pre[N];
struct Edge{int v, rest, p, nxt;
} edge[N * 40];
typedef long long ll;
int col[N], cnt[N], val[N];
bool SPFA() {for (int i = 1; i <= n + m + 10; i++)dist[i] = flow[i] = 1e16, vis[i] = 0;queue<int> q;q.push(S), dist[S] = 0;while (!q.empty()) {int u = q.front();q.pop();vis[u] = 0;for (int i = head[u]; i; i = edge[i].nxt) {if (edge[i].rest && dist[edge[i].v] > dist[u] + edge[i].p) {dist[edge[i].v] = dist[u] + edge[i].p;pre[edge[i].v] = i;flow[edge[i].v] = min(flow[u], edge[i].rest);if (!vis[edge[i].v])q.push(edge[i].v), vis[edge[i].v] = 1;}}}return dist[T] < 1e15;
}
void maxflow() {ll ans = 0, f = 0;//cout << "maxflow" << endl;while (SPFA()) {//cout << "SPFA" << endl;//cout << flow[T] << " " << dist[T] << endl;f += flow[T];ans += flow[T] * dist[T];int x = T;while (x != S) {int y = pre[x];edge[y].rest -= flow[T];edge[y ^ 1].rest += flow[T];x = edge[y ^ 1].v;}}if(f < n / 2)cout << "-1\n";else {ans = -ans;for (int i = 1; i <= n; i++)ans += val[i];cout << ans << '\n';}    
}
void add(int u, int v, int c, int w, int t = 1){edge[++tot] = (Edge){v, c, w, head[u]};head[u] = tot;if(t)add(v, u, 0, -w, 0);
}
void solve(){cin >> n >> m;for(int i = 1; i <= m; i++)cin >> cnt[i], cnt[i] = -cnt[i];n *= 2;for (int i = 1; i <= n; i++){cin >> col[i];cnt[col[i]]++;}for (int i = 1; i <= n; i++)cin >> val[i];//cout << "finish" << endl;memset(head, 0, sizeof head);S = 1, T = 2;tot = 1;add(S, n + 2, n / 2, 0);for (int i = n; i > 1; i--)add(i + 2, i + 1, (i - 1) / 2, 0), add(i + 2, n + 2 + col[i], 1, val[i]);add(1 + 2, n + 2 + col[1], 1, val[1]);bool flag = 1;for (int i = 1; i <= m; i++){add(n + 2 + i, T, cnt[i], 0);if(cnt[i] < 0)flag = 0;}if(flag) maxflow();elsecout << "-1\n";
}signed main(){ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int t = 1;cin>>t;while(t--)solve();return 0;
}//__builtin_popcountll()
// cout<<fixed<<setprecision(2);

M

题意

给出每个提交,包含队伍名、题号、通过情况,问哪个题通过的队伍数最多

整场就这个题是我写的/(ㄒoㄒ)/~~,直接用STL暴力对每个题号的通过队伍名字放set去重,然后遍历map已经是按字典序从小到大,然后判断一下就行。

代码

点击查看代码
#include<bits/stdc++.h>
#define int long long 
#define pb push_back
#define pii pair<int,int>
using namespace std;
bool debug = 1;
#define dbg(x) if(debug) cerr<<BRIGHT_CYAN<<#x<<COLOR_RESET<<" = "<<(x)<<NORMAL_FAINT<<COLOR_RESET<<endl;
const string COLOR_RESET = "\033[0m", BRIGHT_CYAN = "\033[1;36m", NORMAL_FAINT = "\033[0;2m";void solve(){int n; cin >> n;//teamA A acceptedmap<string, set<string>> mp;for (int i = 1; i <= n; i++) {string a, b, c;cin >> a >> b >> c;if (c[0] == 'a') {mp[b].insert(a);}}int mx = 0;string ans;for (auto it : mp) {if (it.second.size() > mx) {mx = it.second.size();ans = it.first;}}cout << ans << "\n";
}signed main(){ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int t = 1;cin>>t;while(t--)solve();return 0;
}//__builtin_popcountll()
// cout<<fixed<<setprecision(2);

L (参考思路)

题意

\(n\) 个点,恰好有一个点没有奶牛,其他都有奶牛,还有 \(l\) 个按钮,每个按钮按下后,可以控制点 \(i\) 处的奶牛移动到 \(t_i\) 位置,只有保证奶牛不能移动到同一个点才能去按按钮。还有 \(q\) 次询问,每次询问,初始没有点的奶牛在 \(a\) 处,最终想要让 \(b\) 点没有奶牛,并且仅使用前 \(c\) 个按钮,问能否实现,用0/1回答。

首先注意到,一个按钮如果能使用,要么移动的到的 \(t_i\) 恰好是一个排列,要么恰有2个 \(t_i\) 相同,且洞位于其中一个位置,否则按按钮必会使奶牛相撞。所以,按一次按钮,相当于让洞移动,而询问相当于问洞从 \(a\) 出发,到达 \(b\),我们就去考虑按按钮对于没有奶牛的洞的影响。对于排列的情况,相当于有一个置换环,因为可以无限次使用按钮,所以同一个环上的点一定可以互相到达。而第二种情况,相当于两条边,(方向还没想好),因为洞只能在重复的那两个点之一。询问相当于问操作前 \(c\) 个按钮,让洞从 \(a\) 移动到 \(b\) 点。所以可以对询问离线,维护每个点到其他点的连通性,但是一直没想到好的维护方法,最后想用bitset冲一下,但是时间来不及了,过样例只剩40s直接交了,赛后看到wa了。不过也知道了是因为前面两条边那个情况应该哪个点往哪个点建边这个没考虑清楚,还是前面做太慢了这题没做出来可惜。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/797749.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

sign与unsigned的原理、数据存储与硬件的关系

目录关键字unsigned和signed数据在计算机中的存储原码 与 补码的转化与硬件关系原,反,补的原理:整型存储的本质变量存取的过程类型目前的作用十进制与二进制快速转换大小端字节序判断当前机器的字节序"负零"(-128)的理解截断建议在无符号类型的数值后带上u, 关键字un…

C++中对象的延迟构造

本文并不讨论“延迟初始化”或者是“懒加载的单例”那样的东西,本文要讨论的是分配某一类型所需的空间后不对类型进行构造(即对象的lifetime没有开始),更通俗点说,就是跳过对象的构造函数执行。 使用场景 我们知道,不管是定义某个类型的对象还是用operator new申请内存,…

黑客失误?76.2万车主,家庭住址信息泄露

​据Cybernews研究团队发现,一个包含76.2W名车主及其车辆详细信息的敏感数据库已经在网上泄露。这些数据托管在一个美国的IP地址上,首次发现是在8月4日,至少暴露了48小时。据该团队称,泄露的数据揭示了车主的敏感信息。泄露的细节几乎揭示了拥有车辆的个人的所有信息,包括…

C++ 在 Visual Studio 如何将指针星号设置成靠近变量而不是类型

“工具”->“选项”->“文本编辑器”->“C/C++”->“代码样式”->“格式设置”->“间距”->“指针/引用对齐方式”->“右对齐”。

Git冲突解决技巧

在多人协作的软件开发项目中,Git 冲突是不可避免的现象。当两个或更多的开发者同时修改了同一段代码,并且尝试将这些修改合并到一起时,冲突就发生了。解决这些冲突是确保代码库健康和项目顺利进行的关键。在多人协作的软件开发项目中,Git 冲突是不可避免的现象。当两个或更…

AI写作助手哪些好用?6款强大的AI写作助手值得收藏!

在内容创作日益重要的今天,AI写作助手已经成为许多创作者的得力工具。它们不仅能够提高写作效率,还能在一定程度上保证文章质量。面对市场上琳琅满目的AI写作助手,如何选择一款好用且适合自己的工具呢?以下推荐6款强大的AI写作助手,它们各具优势,助力创作者轻松应对各种写…

1928.规定时间内到达终点的最小话费,题解

1928. 规定时间内到达终点的最小花费 - 力扣(LeetCode) 有点难,参考官方题解代码: 利用了动态规划思想,逐步计算从起点到各个城市在不同时间下的最小费用。 1.代码解释,涉及,static关键字,constexpr关键字,INT_MAX除以2赋值的含义static constexpr int INFTY = INT_MA…

软件技术基础的第一次作业

这个作业属于哪个课程 https://edu.cnblogs.com/campus/zjlg/rjjc这个作业的目标 向教师和助教介绍自己,并熟悉博客园 对课程的期望姓名 颜宇航学号 20223293011251.个人介绍 大家好,我是22自动化2班的颜宇航,来自浙江台州。很高兴能够在这里与大家分享自己的生活!我是一个…

帝国cms密码忘记,帝国cms网站忘记登陆账号密码

如果你忘记了帝国CMS的管理员账号和密码,可以通过以下几种方法来找回或重置密码: 1. 通过数据库直接修改密码 如果你对数据库操作比较熟悉,可以采用此方法:登录数据库管理工具:使用phpMyAdmin或其他数据库管理工具登录到你的数据库。 找到管理员表:在数据库中找到存储管理…

Ubuntu Server 24.04 LTS 安装记事

Ubuntu Server 24.04 LTS,代号 Noble Numbat,于 2024 年 4 月 25 日正式发布,该发布版可以支持长达12年。 曾经接触Ubuntu的时候,还是它的第一个版本,但是那个时候网络太局限了,关于这个系统的书籍也很少,所以就一直没有使用起来。 有时候好像什么事情都得有个名头,就像…