「HGOI#2019.4.19省选模拟赛」赛后总结
t1-Painting
这道题目比较简单,但是我比较弱就只是写了一个链表合并和区间DP。
别人的贪心吊打我的DP,嘤嘤嘤。
#include <bits/stdc++.h>
#define ll long long
using namespace std;
namespace chhokmah {
#define N 100005
#define M 5005
int a[N], l[M], r[M], pos[N];
int n, m, cnt;
ll sum[M], f[M][M];
ll ans = 0;
ll calc(int cnt) {
for (int i = 1; i <= cnt; i ++) sum[i] += sum[i - 1];
for (int i = cnt; i; i --)
for (int j = i; j <= cnt; j ++)
f[i][j] = max(f[i][j - 1], f[i + 1][j]) + sum[j] - sum[i - 1];
return f[1][cnt];
}
void chhokmah() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i ++) scanf("%d", &a[i]);
for (int i = 1; i <= n; i ++) r[a[i]] = i;
for (int i = n; i; i --) l[a[i]] = i;
for (int i = 1; i <= m; i ++) pos[l[i]] = i;
for (int i = 1; i <= n; i ++) {
if (pos[i]) {
int cnt = 0, x = i;
while (pos[x]) { int y = pos[x]; pos[x] = 0; sum[++ cnt] = r[y] - l[y] + 1; x = r[y] + 1; }
ans += calc(cnt);
}
}
cout << ans << endl;
} }
int main() { chhokmah::chhokmah(); return 0; }
t2-Path
很显然是一道期望\(DP\)。这一道题目还是\(Bluesky\)大佬教我做的,先%为敬。
考虑到最优的策略,一定是从当前算出期望概率较小的点来更新较大的点。
以下是\(BlueSky\)大佬的题解
考虑是按照最优策略进行移动,如果开放一条边且子节点不会使答案变劣,那么就一定会沿该边走向子节点,否则停留在原地。
假设对于点\(i\),不会使答案变劣的点数为\(degree_i\),那么意味着有\(degree_i\)种可能会移动,有\(m-degree_i\)种可能不移动。设点\(i\)走到\(n\)的期望距离为\(f_i\),则有
\[
\begin{array}{rrcl}
&\large f_i&\large =&\large \frac{\large\sum_{v\in son}f_v+(m-degree_i)f_i}{\large m}+1\\\\
\large \Rightarrow&\large mf_i&\large =&\large \sum_{v\in son}f_v+(m-degree_i)f_i+m\\\\
\large \Rightarrow&\large degree_if_i&\large =&\large \sum_{v\in son}f_v+m\\\\
\large \Rightarrow&\large f_i&\large =&\large \frac{\large\sum_{v\in son}f_v+m}{\large degree_i}\\\\
\end{array}
\]
考虑最优策略:
向期望距离尽可能小的位置移动,不会重复经过同一个位置。
反着考虑,从期望距离最小的位置倒着走,对期望距离较大的位置更新答案(即尚未经过的位置)。因为期望距离由可能转移到的位置决定,所以记下对于一个位置可能向多少个位置转移以及转移到的位置的期望距离和。总体从\(n\)出发以堆优化dijkstra
的思路跑一遍即可,\(f_1\)就是所求答案。
窝也没有什么可以补充的。
可以稍微讲一下自己在理解时的一些问题。
Q:为什么公式是\(f_i= \frac{\sum_{v\in son}f_v+(m-degree_i)f_i}{ m}+1\)
A:可以理解成走的期望和不走的期望:
设\(sum[i]\)为\(\sum_{v\in son}f_v\)。
走的概率很明显是\(\frac{degree_i}{m}\),那么走的期望就是\(\frac{sum[i]}{m}\)。
考虑不走的话,一定是原先的期望上\(\times\)不走的概率。
不走的概率是\(\frac{m-degree_i}{m}\)
那么不走的期望就是\(\frac{m-degree_i}{m}\times f_i\)
因为无论走还是不走一定会消耗\(1\)的时间,那么需要\(+1\)。
#include <bits/stdc++.h>
#define eps (1e-10)
#define db double
#define ldb long double
#define N 300005
using namespace std;
namespace chhokmah {
struct edge { int to, nt; } E[N << 1];
int H[N], num[N];
ldb f[N], sum[N];
bool vis[N];
int ecnt, n, m;
void add_edge(int u, int v) { E[++ ecnt] = (edge) {v, H[u]}; H[u] = ecnt; }
class cmp {
public:
bool operator() (int i, int j) {
if (fabs(f[i] - f[j]) < eps) return i < j;
else return f[i] < f[j];
}
};
set <int, cmp> now;
set <int, cmp> :: iterator it;
void chhokmah() {
scanf("%d%d", &n, &m);
for (int i = 1, u, v; i <= m; i ++) scanf("%d%d", &u, &v), add_edge(u, v), add_edge(v, u);
f[n] = 0; now.insert(n);
for (int i = 1; i <= n; i ++) {
if (now.empty()) break;
it = now.begin(); int u = (*it); vis[u] = 1; now.erase(u);
for (int e = H[u]; e; e = E[e].nt) {
int v = E[e].to;
if (!vis[v]) {
now.erase(v); num[v] ++;
sum[v] += f[u];
f[v] = (sum[v] + m) / num[v];
now.insert(v);
}
}
}
printf("%0.10f\n", (db) f[1]);
}
}
int main() { chhokmah::chhokmah(); return 0; }
t3-Tree
毒瘤,做不出来。。。
贴一下标称:
#include <stdlib.h>
#include <string.h>
#include <cstdio>
#include <vector>
#include <algorithm>
#define pb push_back
#define sz(a) ((int) (a).size())
using namespace std;
const int N = (int) 3e5;
vector<int> adj[N], who[N], bad[N], path, relax[N];
int n, u, v, root, ans[N], depth[N], h[N], used[N], value[N], it, tlmx[4 * N], trmx[4 * N];
void update(int t, int l, int r, int x, int y) {
if (l == r - 1)
tlmx[t] = y, trmx[t] = y + 1;
else {
int m = (l + r) / 2;
if (x < m) update(t * 2 + 1, l, m, x, y);
else update(t * 2 + 2, m, r, x, y);
tlmx[t] = max(tlmx[t * 2 + 1], (m - l) + tlmx[t * 2 + 2]);
trmx[t] = max(trmx[t * 2 + 2], trmx[t * 2 + 1] + (r - m));
}
}
int get_right(int t, int l, int r, int who, int k) {
if ((l > who) || (trmx[t] + who - r <= k)) return -1;
if (l == r - 1) return l;
int m = (l + r) / 2;
int rvalue = get_right(t * 2 + 2, m, r, who, k);
if (rvalue != -1) return rvalue;
return get_right(t * 2 + 1, l, m, who, k);
}
void get_left(int t, int l, int r, int x, int k, int &lmx, int &res) {
if (l >= x + 1) return;
if (r <= x + 1) {
if (max(tlmx[t], r - l + lmx) < k) {
lmx = max(tlmx[t], r - l + lmx);
return;
} else if (l == r - 1) {
res = l;
return;
}
}
int m = (l + r) / 2;
get_left(t * 2 + 2, m, r, x, k, lmx, res);
if (res == -1) get_left(t * 2 + 1, l, m, x, k, lmx, res);
}
void set_value(int depth, int nvalue) {
update(0, 0, h[root] + 1, depth, nvalue);
value[depth] = nvalue;
}
void update_answer(int k, int who) {
int marked = get_right(0, 0, h[root] + 1, who, k), lmx = -1, res = -1;
if (marked == -1) return;
get_left(0, 0, h[root] + 1, marked, k, lmx, res);
if (res == -1) res = 0;
if (value[res] <= k) relax[path[res]].pb(k);
else bad[path[res]][k] = max(bad[path[res]][k], lmx + 1);
}
void dfs(int v) {
path.pb(v);
int mx_u = -1, pre_mx_u = -1;
for (int i = 0; i < sz(adj[v]); ++i) {
int u = adj[v][i];
if ((mx_u == -1) || (h[mx_u] < h[u])) pre_mx_u = mx_u, mx_u = u;
else if ((pre_mx_u == -1) || (h[pre_mx_u] < h[u])) pre_mx_u = u;
}
bad[v] = vector<int>((pre_mx_u == -1) ? 1 : (1 + h[pre_mx_u]), 0);
for (int i = 0; i < sz(adj[v]); ++i) {
int u = adj[v][i];
set_value(depth[v], (u == mx_u) ? ((pre_mx_u == -1) ? 0 : (h[pre_mx_u] + 1)) : (h[mx_u] + 1));
dfs(u);
}
if (mx_u != -1) {
who[v].swap(who[mx_u]), ++it;
for (int i = 0; i < sz(adj[v]); ++i) {
int u = adj[v][i];
if (mx_u == u) continue;
used[h[u] + 1] = it;
for (int k = 0; k <= h[u]; ++k)
who[v][k] = min(who[v][k], who[u][k]);
}
for (int k = 0, mx = 0; k <= ((pre_mx_u == -1) ? -1 : h[pre_mx_u]); ++k) {
if (used[k] == it) mx = k;
set_value(depth[v], max(mx, bad[v][k]));
update_answer(k, who[v][k]);
}
}
who[v].pb(depth[v]);
set_value(depth[v], 0);
relax[v].pb(h[v]);
for (int i = 0; i < sz(relax[v]); ++i) {
int k = relax[v][i];
ans[k]++, who[v][k] = depth[v];
update_answer(k, depth[v]);
}
path.pop_back();
}
void calc_h(int v, int p = -1) {
for (int i = sz(adj[v]) - 1; i >= 0; --i) {
int u = adj[v][i];
if (u == p) {
swap(adj[v][i], adj[v].back());
adj[v].pop_back();
} else {
depth[u] = depth[v] + 1;
calc_h(u, v);
h[v] = max(h[v], h[u] + 1);
}
}
}
int main() {
scanf("%d", &n);
for (int i = 0; i + 1 < n; ++i) {
scanf("%d%d", &u, &v), --u, --v;
adj[u].pb(v), adj[v].pb(u);
}
root = 0;
calc_h(root);
for (int i = 0; i < n; i ++) cout <<
dfs(root);
for (int d = h[root] + 1; d <= n; ++d)
ans[d] = 1;
for (int k = 1, d = n; k <= n; ++k) {
while ((d > 0) && (ans[d - 1] <= k)) --d;
printf("%d%c", d, " \n"[k == n]);
}
return 0;
}
「HGOI#2019.4.19省选模拟赛」赛后总结的更多相关文章
- 5.19 省选模拟赛 小B的夏令营 概率 dp 前缀和优化dp
LINK:小B的夏令营 这道题是以前从没见过的优化dp的方法 不过也在情理之中. 注意读题 千万不要像我这个sb一样 考完连题意都不知道是啥. 一个长方形 要求从上到下联通的概率. 容易发现 K天只是 ...
- 5.19 省选模拟赛 小B的图 最小生成树 LCT
LINK:小B的图 这道题就比较容易了. 容易想到将询问离线 然后 从小到大排序 那么显然是优先放正图(x+k)的边. 考虑随着x的增大 那么负图上的边会逐渐加进来 一条边被加进来当且仅当 其权值小于 ...
- 5.19 省选模拟赛 T1 小B的棋盘 双指针 性质
LINK:小B的棋盘 考试的时候没有认真的思考 导致没做出来. 容易发现 当k>=n的时候存在无限解 其余都存在有限解 对于30分 容易想到暴力枚举 对称中心 然后 n^2判断. 对于前者 容易 ...
- 「CSP-S模拟赛」2019第四场
「CSP-S模拟赛」2019第四场 T1 「JOI 2014 Final」JOI 徽章 题目 考场思考(正解) T2 「JOI 2015 Final」分蛋糕 2 题目 考场思考(正解) T3 「CQO ...
- #10470. 「2020-10-02 提高模拟赛」流水线 (line)
题面:#10470. 「2020-10-02 提高模拟赛」流水线 (line) 题目中的那么多区间的条件让人感觉极其难以维护,而且贪心的做法感觉大多都能 hack 掉,因此考虑寻找一些性质,然后再设计 ...
- 【洛谷比赛】[LnOI2019]长脖子鹿省选模拟赛 T1 题解
今天是[LnOI2019]长脖子鹿省选模拟赛的时间,小编表示考的不怎么样,改了半天也只会改第一题,那也先呈上题解吧. T1:P5248 [LnOI2019SP]快速多项式变换(FPT) 一看这题就很手 ...
- #10471. 「2020-10-02 提高模拟赛」灌溉 (water)
题面:#10471. 「2020-10-02 提高模拟赛」灌溉 (water) 假设只有一组询问,我们可以用二分求解:二分最大距离是多少,然后找到深度最大的结点,并且把它的\(k\)倍祖先的一整子树删 ...
- 「NOIP模拟赛」数位和乘积(dp,高精)
统计方案数,要么组合数,要么递推(dp)了. 这是有模拟赛历史以来爆炸最狠的一次 T1写了正解,也想到开long long,但是开错了地方然后数组开大了结果100->0 T3看错题本来简单模拟又 ...
- ZROI 19.08.07模拟赛
传送门 写在前面:为了保护正睿题目版权,这里不放题面,只写题解. "正睿从来没有保证,模拟赛的题目必须原创." "文案不是我写的,有问题找喵老师去."--蔡老师 ...
随机推荐
- linux快捷进入长目录的方法
快捷命令 :alias chaoyang ='cd /usr/lib/uu/hh/lib' 1.将上述设置写到家目录的.bashrc文件中(~/.bashrc) 2.然后source ./bash ...
- dotNet core 应用部署至 centos(超详解附截图)
文章来源:公众号-智能化IT系统. 需要安装的插件以及支撑架构 1.dotnetSDK dotnet 相关命令是属于 .NET Core command-line (CLI) 的一部分,Microso ...
- leaflet动态路径
在leaflet中使用动态路径需要结合插件使用,对比了好几个插件,最终找到leaflet.motion比较合适: leaflet地址:https://leafletjs.com/ leaflet.mo ...
- python文章装饰器理解12步
1. 函数 在python中,函数通过def关键字.函数名和可选的参数列表定义.通过return关键字返回值.我们举例来说明如何定义和调用一个简单的函数: def foo(): return 1 fo ...
- 第二节 pandas 基础知识
pandas 两种数据结构 Series和DataFrame 一 Series 一种类似与一维数组的对象 values:一组数据(ndarray类型) index:相关的数据索引标签 1.1 se ...
- Enterprise Architect 时序图
添加时序图 1,在类图下面新建包 添加sequence时序图 点击流程控制,可以打开流程控制设计界面 我选择的是Lifeline线,你可以选择都差不多. 点击其中一条liftline连到其他上面 双击 ...
- Spring MVC @RequestMapping注解详解
@RequestMapping 参数说明 value:定义处理方法的请求的 URL 地址.(重点) method:定义处理方法的 http method 类型,如 GET.POST 等.(重点) pa ...
- [LeetCode] 16. 最接近的三数之和
题目链接:https://leetcode-cn.com/problems/3sum-closest/ 题目描述: 给定一个包括 n 个整数的数组 nums 和 一个目标值 target.找出 num ...
- 数据类型:list列表[]、元祖tuple()、dict字典{}
List 列表[] 可变的 lst = [1,2,3,4] #改 lst[(元素下标)] = '需要修改的' #通过下表修改 lst[下标:下标] = '需要修改的' #通过范围修改 #加 lst.a ...
- html基础和CSS选择器
一.html简单基础 什么是HTML HTML 是用来描述网页的一种语言. HTML 指的是超文本标记语言: HyperText Markup Language HTML 不是一种编程语言,而是一种标 ...