1006.Maex

题意:

给定一棵由从 1 到 n 编号的 n 个顶点组成的有根树,根为顶点 1。顶点 i 有一个自然数权重 ai,并且没有两个不同的顶点具有相同的权重。bu是以u为根的子树的权重的MEX,ai未知,求最大的bi和。

题解:

用sz[u]表示u子树节点个数, 表示dp[u]子树内sum(bi)可以达到的最大值。
那么考虑转移,u本身的b[u]一定可以是sz[u],而因为a必须两两不同,0只能在u的某个子树内,所以除了某个子树,其他子树节点的bi一定都为0.
那么转移就是:dp[u] = sz[u] +max(dp[v])

代码:

#include<iostream>
#include<set>
#include<string>
#include<vector>
#include<cstring>
#include<queue>
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;const int N = 1e6 + 10;int n;
vector<int> g[N];
int siz[N], dp[N];void dfs(int u, int fr){siz[u] = 1, dp[u] = 0;for(auto v : g[u]){if(v == fr) continue;dfs(v, u);siz[u] += siz[v];dp[u] = max(dp[u], dp[v]);}dp[u] += siz[u];
}void solve(){cin >> n;for(int i = 0; i < n; i++) g[i].clear();for(int i = 1; i < n; i++){int u, v;cin >> u >> v;u --, v --;g[u].push_back(v);g[v].push_back(u);}dfs(0, -1);cout << dp[0] << '\n';
}signed main(){ios::sync_with_stdio(0);cin.tie(0); cout.tie(0);int t;cin >> t;while(t--){solve();}
}

1012.Loop

题意:

给定一个数列,在指定操作数内,可以选择一段区间,将区间内的数字左移一位,最左边的数字移到最右边,问最大字典序的结果。

题解:

每次贪心地将第一个ai  < ai+1的数放到第一个小于它的数前面。

代码:

#include<iostream>
#include<set>
#include<string>
#include<vector>
#include<cstring>
#include<queue>
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;const int N = 1e6 + 10;int n, k;
int a[N], b[N], ans[N];void solve(){cin >> n >> k;for(int i = 1; i <= n ;i++) cin >> a[i];int tot = 0, num = 0;priority_queue<int> q;for(int i = 1; i <= n; i++){while(tot && b[tot] < a[i] && k){k --;q.push(b[tot]);tot --;}b[++tot] = a[i];}for(int i = 1, p = 1; i <= n; i++){if(p > tot){ans[++num] = q.top();q.pop();}else if(q.empty()){ans[++num] = b[p++];}else{if(b[p] < q.top()){ans[++num] = q.top();q.pop();}else ans[++num] = b[p++];}}for(int i = 1;i <= n; i++) cout << ans[i] << (i == n ? '\n' : ' ');
}signed main(){ios::sync_with_stdio(0);cin.tie(0); cout.tie(0);int t;cin >> t;while(t--){solve();}
}

1009.Map

题意:

给定一张大地图和小地图,两张贴在一起,问重合点的坐标。

题解:

用向量,相似三角形和阿波罗尼斯圆都可以轻松解决。

代码:

#include<iostream>
#include<cmath>
#include<iomanip>
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;const int N = 1e6 + 10;double k;
int x[9], y[9];double dis(int i, int j)
{return sqrt((x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j]));
}void solve(){for(int i = 1; i <= 8; ++i)cin >> x[i] >> y[i];k=dis(1, 2) / dis(5, 6);double A = (x[4] - x[1]) / dis(1, 4) - (x[8] - x[5]) / k / dis(5, 8);double B = (x[2] - x[1]) / dis(1,2) - (x[6] - x[5]) / k / dis(5, 6);double C = x[5] - x[1];double D = (y[4] - y[1]) / dis(1, 4) - (y[8] - y[5]) / k / dis(5, 8);double E = (y[2] - y[1]) / dis(1, 2) - (y[6] - y[5]) / k / dis(5, 6);double F = y[5] - y[1];double ansx = (B * F - C * E) / (B * D - A * E);double ansy = (C * D - A * F) / (B * D - A * E);cout << x[1] + (x[2] - x[1]) * ansy / dis(1, 2) + (x[4] - x[1]) * ansx / dis(1, 4) << " ";cout << y[1] + (y[2] - y[1]) * ansy / dis(1, 2) + (y[4] - y[1]) * ansx / dis(1, 4) << '\n';
}signed main(){ios::sync_with_stdio(0);cin.tie(0); cout.tie(0);cout << fixed << setprecision(9);int t;cin >> t;while(t--){solve();}
}

1010.Planar Graph

题意:

给定一张图,问最少需要去掉几条边,使图只有一个面,并给出删掉的边。

题解:

本题的题目背景是平面图欧拉定理的一种证明方式. 根据平面图欧拉定理V - E + F = k + 1 (V,E,F,k 分别为点, 边, 面, 连通分量的个数), 每去掉一条边(加一个隧道可以理解为删除一条边), 平面图G的面的个数就会增加 . 因此最终边的个数为V + 1 - k - 1 = V - k, 因此删边个数为E - V + k. 于是对于每个连通分量, 保留了V' - 1条边(V'为该连通分量的点数). 如果该连通分量有圈, 那么这个圈内的区域一定不与外部的无穷平面连通, 不符合题意. 因此每个连通分量都不含圈, 且有V' - 1条边, 因此每个连通分量都变成树.
现在从另外一个角度考虑. 我们构造一个新图G'. 我们把平面图的每个面当作一个点, 如果两个面被平面图的某条边分隔, 那么这两个面在 对应的点之间连一条边(于是G和G'的边是一一对应关系).G'的点个数为F = k + 1 - V + E,G的删边个数为E - V +k = F - 1, 由于建隧道之后任意两个区域可达, 因此如果把G中删掉的边在G'中考虑, 删除G'中在G保留的边, 那么边个数为F - 1, 且任意两点连通. 因此这些边构成G'的生成树.
于是, 问题转化为求G'的字典序最小的生成树. 由于每条边边权不同, 因此字典序最小的生成树等价于G'最小生成树, 等价于G的生成树边权和最小(考虑kruskal算法的构造过程, 并注意所有边权不同时最小生成树唯一). 由于所有边边权和为定值, 因此G'生成树边权和最小等价于G的每个连通分量对应的树边权和最大. 于是只需要对于G的每个连通分量求出最大生成树, 然后这些最大生成树没有用到的边就是G'的最小生成树的边.

代码:

#include<iostream>
#include<cmath>
#include<iomanip>
#include<cstring>
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;const int N = 1e5 + 10;int n, m;
int p[N], vis[N << 1], u[N << 1], v[N << 1];int dsu(int x){return p[x] == x ? x : p[x] = dsu(p[x]);
}void init(){memset(vis, 0, sizeof(vis));memset(p, 0, sizeof(p));memset(u, 0, sizeof(u));memset(v, 0, sizeof(v));
}void solve(){init();cin >> n >> m;for(int i = 1; i <= n; i++) p[i] = i;for(int i = 1; i <= m; i++) cin >> u[i] >> v[i];int tot = m;for(int i = m; i >= 1; i--){int x = dsu(u[i]), y = dsu(v[i]);if(x != y){tot --;vis[i] = 1;p[x] = y;}}cout << tot << '\n';for(int i =1 ; i <= m; i++){if(!vis[i]) cout << i << ' ';}cout << '\n';
}signed main(){ios::sync_with_stdio(0);cin.tie(0); cout.tie(0);//cout << fixed << setprecision(9);int t;cin >> t;while(t--){solve();}
}

1007.Shinobu loves trip

题意:

有P个城市,P为质数,对于编号为i的城市,第二天只能到达编号为(i * a)% P的城市。现在有n个旅游计划,包含起点和天数,有若干个询问,每次问路经一个指定城市的计划数。

题解:

从s走d天之后会来到(s * a) %P,因此,判断一个点x是否会被一个计划经过,只需要判断是否存在一个0 ≤ k ≤ d使得(s * ) % P = x,由于P是质数,所以已知x和s的值,可以得到的值。
预处理所有a的0次方到200000次方,然后直接查询算出来的是否在预处理出的数里面,如果不在,这个计划一定不经过x,否则可以得到k的具体值,判断k ≤ d即可。
要注意特判s = 0的情况。

代码:

#include<iostream>
#include<cmath>
#include<assert.h>
#include<iomanip>
#include<vector>
#include<cstring>
#include<unordered_map>
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;const int N = 2e5 + 10;int p, a, n ,q;int qm(int a, int b, const int p){int res = 1;while(b){if(b % 2) res = res * a % p;a = a * a % p;b >>= 1;}return res;
}void solve(){cin >> p >> a >> n >> q;assert(p > 2 && p <= 1e9 + 7);assert(a >= 2 && a < p);assert(n <= 1000 && n > 0);assert(q <= 1000 && q > 0);unordered_map<int, int> f;vector<int> s(n), is(n), d(n);int cur = 1, len = 0;while(len < N && !f.count(cur)){f[cur] = len;cur = cur * a % p;len ++;}for(int i = 0; i < n; i ++){cin >> s[i] >> d[i];assert(s[i] < p && s[i] >= 0);assert(d[i] <= 200000 && d[i] >= 1);if(s[i]) is[i] = qm(s[i], p - 2, p);}while(q--){int x;cin >> x;assert(x >= 0 && x < p);int ans = 0;if(x == 0) {for(int i = 0; i < n; i++) if(s[i] == 0) ans ++;}else{for(int i = 0; i < n; i++){if(s[i] == 0) continue;int ak = x * is[i] % p;if(f.count(ak) && f[ak] <= d[i]) ans++;}}cout << ans << '\n';}
}signed main(){ios::sync_with_stdio(0);cin.tie(0); cout.tie(0);//cout << fixed << setprecision(9);int t;cin >> t;assert(t <= 5 && t > 0);while(t--){solve();}
}

2022“杭电杯”中国大学生算法设计超级联赛(6)题解报告相关推荐

  1. 2022“杭电杯”中国大学生算法设计超级联赛(8)

    2022"杭电杯"中国大学生算法设计超级联赛(8) [题目链接](Search Result (hdu.edu.cn)) D Quel'Thalas 题目大意 在二维平面上,[0, ...

  2. 2022“杭电杯”中国大学生算法设计超级联赛(4)

    2022"杭电杯"中国大学生算法设计超级联赛(4) [题目链接](Search Result (hdu.edu.cn)) D Link with Equilateral Trian ...

  3. 2022“杭电杯”中国大学生算法设计超级联赛 (1) 杭电多校第一场 2 3 4 5 8 12

    题目 1002 Dragon slayer 标程 1003 Backpack AC代码 1004 Ball AC代码 1008 Path AC代码 1009 Laser AC代码 1012 Alice ...

  4. 2022“杭电杯”中国大学生算法设计超级联赛 (2) 杭电多校第二场

    题目 1001 Static Query on Tree AC代码 1002 C++ to Python AC代码 1003 Copy AC代码 1005 Slayers Come AC代码 1007 ...

  5. 2022“杭电杯”中国大学生算法设计超级联赛(8)题解报告

    Problem D. Quel'Thalas 题解: 手玩一下就会发现答案是就是2n. 代码: #include<iostream> #include<algorithm> # ...

  6. 2022“杭电杯”中国大学生算法设计超级联赛(2)1003.Copy

    样例输入: 1 5 3 1 2 3 4 5 2 4 1 2 4 2 5 样例输出: 6  题意: 有q次操作,有以下两种: 1.选择区间[l,r],复制[l,r]追加到r后,总的数组的大小(n)不变 ...

  7. 2022“杭电杯”中国大学生算法设计超级联赛(8)补题

    1004  Quel'Thalas 题意 在二维平面上,点在坐标在[0,n]的区间内,通过添加无限长的直线可以覆盖这些点,在不覆盖(0,0)的情况下要添加多少根直线. 思路 在两个方向上添加直线,所以 ...

  8. 2022“杭电杯”中国大学生算法设计超级联赛(8)补题 1011 (持续更新中)

    目录 1011 Stormwind(贪心--分割矩形) 1011 Stormwind(贪心–分割矩形) /*题解:想要切割的次数最多,让原矩形的一边尽可能被多次切割,另一边紧跟即可*/ #includ ...

  9. 2022“杭电杯”中国大学生算法设计超级联赛(1)1003 Backpack个人题解

    Backpack 题目描述 有n件物品,他们各自都有体积vi和价值wi,给你一个体积为m的背包,求是否能从这n件物品中取出若干件,使得它们的体积之和恰好为m,所有物品的异或和最大,最大值是多少 分析 ...

最新文章

  1. 他总在逆风翻盘,绝地反击!最不爱钱却成了最有钱的人...
  2. python第四十一天---作业:简单FTP
  3. 简单的对象监听器 观察者设计模式
  4. 【MM配置】Global Data 全局数据相关配置
  5. 一个简单的linux线程池
  6. tf.gfile()函数
  7. PyTorch(总)---PyTorch遇到令人迷人的BUG与记录
  8. php db类 应用实例,PHP-Laravel(DB类操作数据库)
  9. matlab画空间直线,空间直线x y=z怎么画
  10. web前端js上传文件
  11. oracle建表唯一约束语句,oracle 详细建表语句
  12. 离散数学计算机科学与技术答案,湘潭大学计算机科学与技术刘任任版离散数学课后习题答案---第二学期--图论与组合数学...
  13. 算法设计 分治法 快速排序 C语言实现
  14. 2020计算机校友会大学排名,2020年校友会大学排名:一个世界一流大学,一个中国一流大学...
  15. 有道云笔记不同步_有道云笔记不能无法同步解决教程
  16. Docker开启TLS和CA认证, 解决暴露2375端口引发的安全漏洞, 并使用idea连接并推送镜像
  17. 爬虫数据储存—CSV文件
  18. linux在磁盘容量扩容后扩容文件系统
  19. 什么是matlab的幅值域,基于LabVIEW的虚拟频谱分析仪
  20. Understand for linux

热门文章

  1. Navicat链接数据库奇葩错误
  2. 微信小程序自定义组件——添加图片组件
  3. Android 8.0 行为变更
  4. html 显示 数据库图片.js,html实时显示数据 怎么让数据库的数据在html显示出来
  5. 甲骨文的项目Kenai U-Turn
  6. 利用SURF特征检测和FLANN最近邻算法实现图像的目标提取
  7. 逆天的chitgpt
  8. LBS游戏火拼三要素:位置、情感、3D渲染
  9. 浅析std::string的append方法
  10. Python分支基础题练习(1. 英制单位和公制单位互换 2.掷骰子决定做什么 3.分段函数求值 4.输入三条边的长度如果能构成三角形就计算周长和面积)