直接开写题解:

(由于T1为暴力模拟,不进行整理)

T2:

扶苏给了你一棵树,这棵树上长满了幼嫩的新叶,我们约定这棵树的根是 1,每个节 点都代表树上的一个叶子。 如果你不知道什么叫树,你可以认为树是一个边数比节点个数少 1 的无向连通图。 我们如果约定节点 u 是树 T 的根,则可以定义一个节点 v 到根的路径为该无向图上 u, v 两个节点之间的简单路径上的节点集合(包括路径的两个端点)。可以证明,这样的简单路 径只有一条。 我们定义节点 x 是节点 y 的祖先(x 不等于 y),当且仅当 x 在 y 到根的路径上。 现在扶苏想在这棵树上选定一个集合,将其称之为幼嫩集合,来比较集合中的节点 哪个最幼嫩。注意到一旦集合中存在两个节点 u, v,使得 u 是 v 的祖先,那么一定 v 要比 u 更幼嫩,因为 v 是在 u 的枝丫上生长出来的,那么这样的集合就是没有意义的。也就是 说,扶苏所选择的集合一定满足要求“对于任意集合中的元素对 (u, v),u 不是 v 的祖 先”。 扶苏其实对这些节点哪个最幼嫩并不感兴趣,也对他能选出多少集合不感兴趣,因 为这些都是为了问你下面的问题而创造出的题目背景。 扶苏给每个节点都定义了一个权值,具体的,我们会给出一个参数 T,规定 i 号节点 的权值为 T i 。 我们定义一个幼嫩集合幼嫩指数为集合内节点的权值和。现在扶苏想请问你,对于 他所有可能选出的集合,这些集合的幼嫩指数之和是多少。 为了避免答案过大,请你输出答案对1000000007取模的结果。

ZAY大佬分层讲了几种方法,分别可以拿到不同层级的分,

1.直接输出答案,只得第一问的分

2.暴搜,复杂度较高,但能拿到30分

3.DP

我们可以把这样的标签:

变成这样的:

考虑将每个节点的状态用子节点表示

1.二叉树状态,每个节点仅有两个分支

先考虑边界条件,即该节点是叶节点时,它没有子树甚至子节点,于是他自己的贡献为自身权值,

再考虑有两个子节点的节点,其上之节点选择方案共有4种,分别是左节点,右节点,自己,左右两节点

再由乘法原理易推知,当前节点的方案总数即为子树根节点方案总数加1之积,就是两子树互相搭配情况下,再算上某子树自身不算的方案总数,这也就是+1的用处

而每个节点的分数就是某棵子树根节点分数乘另一棵子树方案总数,就是自己被选了多少次,由此,可推出答案

2.非二叉树,

每次将同一层的最左端的两棵子树进行如上操作,再将其看作一整体,与下一棵子树进行处理,直到所有子树处理完成

按照以上DP思想处理就可以那全分辣!

代码:

#include <cstdio>

typedef long long int ll;

const int maxn = ;
const int MOD = ; template <typename T>
inline void qr(T &x) {
char ch;
do { ch = getchar(); } while ((ch > '') || (ch < ''));
do { x = (x << ) + (x << ) + (ch ^ ); ch = getchar(); } while ((ch >= '') && (ch <= ''));
} int n, T;
int MU[maxn], frog[maxn], gorf[maxn];
bool vis[maxn]; struct Edge {
int v;
Edge *nxt; Edge(const int _v, Edge *h) : v(_v), nxt(h) {}
};
Edge *hd[maxn]; void dfs(const int u); int main() {
freopen("dzy.in", "r", stdin);
freopen("dzy.out", "w", stdout);
qr(n); qr(T);
if (T) {
for (int i = ; i <= n; ++i) {
MU[i] = i;
}
} else {
for (int i = ; i <= n; ++i) {
MU[i] = ;
}
}
for (int i = , u, v; i < n; ++i) {
u = v = ; qr(u); qr(v);
hd[u] = new Edge(v, hd[u]);
hd[v] = new Edge(u, hd[v]);
}
dfs();
printf("%d\n", frog[] % MOD);
return ;
} void dfs(const int u) {
vis[u] = true;
for (auto e = hd[u]; e; e = e->nxt) if (!vis[e->v]) {
int v = e->v;
dfs(v);
frog[u] = (frog[u] * (gorf[v] + 1ll) % MOD) + (frog[v] * (gorf[u] + 1ll) % MOD);
gorf[u] = (gorf[u] + gorf[v] + (1ll * gorf[u] * gorf[v])) % MOD;
}
frog[u] = (frog[u] + MU[u]) % MOD;
++gorf[u];
}

这么诡异的码风肯定是zay的啊

T3:

在一个兵荒马乱的年代,有一位画师叫浅溪,非常喜欢画锦鲤。战火烧到了泰 安,他的邻居都惊慌逃命,只有他不舍得池中锦鲤没有离开。这天晚上庭院失火, 池中的锦鲤化妖,用生命护住了画师的平安。

扶苏被画师和锦鲤的故事深深地打动了。为了能让锦鲤和画师继续生活在一起,他 决定回到着火的庭院中灭掉大火。 画师的庭院可以抽象成一个有向图,每个点代表着一个着火的位置。为了量化火势 的大小,扶苏给每个点一个火力值,火力值越大,代表这个点的火势越强。风助火势, 火借风力,对于每一个着火点,都有可能因为大风使得火扩散到其他点。有向图的每条 边 <u,v> 代表大火是从点 u 扩散到点 v 的。需要注意的是一个点可能会扩散到很多 点,也可能是由很多点的大火一起扩散成的。为了不因为灭掉火源让画师发现有人在帮 他灭火,在任意时刻,扶苏不能灭掉任何一个不被任何点所扩散的点的火。一个点的火 被灭掉后,所代表该点的火扩散的所有边将消失。需要说明的是,虽然边消失了,但是 该点扩散到的所有点属性除入度以外都不会改变,更不会消失。 因为穿越的时间有限,扶苏只能灭掉最多 k 个点的火。忙着写题面的扶苏没有时间 算出他最多能扑灭多少火力值,于是他把这个问题交给了你。

便于理解的题面版本: 给你一张有向图,每个点有一个点权。你可以任意选择一个有入度的点,获得它的 点权并把它和它的出边从图上删去。任意时刻不能选择没有入度的点。最多能选择 k 个 点,求最多能获得多少点权。   md我花了10分钟读题你告诉我有简化版???!!!

老规矩:

1.输出样例 5分(我连输出都没打完就输出答案了,然而建树模板从T2粘下来的,一波窒息操作CE了)

2.暴搜

3.拓扑排序+贪心(有这个思路但时间不够了这题目背景竟该死的甜美)

4.也是拓扑,利用深搜原理和强连通分量性质对环进行缩点(tarjan),对于搜索树进行贪心,完成...

我TM刚刚整了套什么?

我们整个下午差不多听题解也是这么个状态:

啊...就是这个这个...那个那个...讲的好啊!

1 minite later

(小声)你听懂了吗?

代码奉上:

#include <cstdio>
#include <algorithm>
#include <functional>
#ifdef ONLINE_JUDGE
#define freopen(a, b, c)
#endif typedef long long int ll; namespace IPT {
const int L = ;
char buf[L], *front=buf, *end=buf;
char GetChar() {
if (front == end) {
end = buf + fread(front = buf, , L, stdin);
if (front == end) return -;
}
return *(front++);
}
} template <typename T>
inline void qr(T &x) {
char ch = IPT::GetChar(), lst = ' ';
while ((ch > '') || (ch < '')) lst = ch, ch=IPT::GetChar();
while ((ch >= '') && (ch <= '')) x = (x << ) + (x << ) + (ch ^ ), ch = IPT::GetChar();
if (lst == '-') x = -x;
} const int maxn = ; struct Edge {
int v;
Edge *nxt; Edge(const int _v, Edge *h) : v(_v), nxt(h) {}
};
Edge *hd[maxn]; int n, m, k, vistime, top, scnt;
int MU[maxn], dfn[maxn], low[maxn], stack[maxn], belong[maxn], minv[maxn];
bool instack[maxn], haveind[maxn]; void tarjan(const int u); int main() {
freopen("zay.in", "r", stdin);
freopen("zay.out", "w", stdout);
qr(n); qr(m); qr(k); MU[] = ;
for (int i = ; i <= n; ++i) qr(MU[i]);
for (int i = , u, v; i <= m; ++i) {
u = v = ; qr(u); qr(v);
hd[u] = new Edge(v, hd[u]);
}
for (int i = ; i <= n; ++i) if (!dfn[i]) {
tarjan(i);
}
for (int u = ; u <= n; ++u) {
for (auto e = hd[u]; e; e = e->nxt) if (belong[u] != belong[e->v]) {
haveind[belong[e->v]] = true;
}
}
for (int i = ; i <= scnt; ++i) if (!haveind[i]) {
MU[minv[i]] = ;
}
std::nth_element(MU + , MU + + k, MU + + n, std::greater<int>());
int ans = ;
for (int i = ; i <= k; ++i) {
ans += MU[i];
}
printf("%d\n", ans);
return ;
} void tarjan(const int u) {
dfn[u] = low[u] = ++vistime;
instack[stack[++top] = u] = true;
for (auto e = hd[u]; e; e = e->nxt) {
int v = e->v;
if (!dfn[v]) {
tarjan(v);
low[u] = std::min(low[u], low[v]);
} else if (instack[v]) {
low[u] = std::min(low[u], dfn[v]);
}
}
if (dfn[u] == low[u]) {
int v, &_mv = minv[++scnt];
do {
instack[v = stack[top--]] = false;
belong[v] = scnt;
if (MU[v] < MU[_mv]) _mv = v;
} while (v != u);
}
}

不打using namespace std的神仙...

讲解内容放在这里,看培训完了能不能听懂...

考虑DAG的情况放到普通有向图上会发生什么。

有了子任务 3 的提示,我们可以考虑把整个图缩点,将其变成一个DAG来做。

对于一个DAG,显然可以通过子任务 3 调整顺序的方式使得每个强连通分量的 选择情况除选点个数以外互不影响。故下面只讨论一个强连通分量内部的情况。

一个强连通分量显然可以看作是一棵外向树加上很多边得到的。

一棵外向树的定义:一个外向树的任意一个节点要么为叶节点,要么它与孩子 间的所有边都是由它指向孩子。

一棵外向树显然是一个 DAG 。按照之前对 DAG 上情况的说明,显然我们可以 选择除了根节点以外的任意节点。

因为一个强连通分量内部是互相连通的,于是我们不妨钦定一个点为根。

对于一个没有入度的强连通分量,我们不妨钦定点权最小的点为根。这样显然选择的是最优的。

对于一个有入度的强连通分量,我们不妨钦定那个有入度的点为根。这样在选择到只剩根节点的时候,因为根节点有入度,所以根节点是可以被选择的。于是这个强连通分量可以被全部选择。这显然是最优的。

这样综合上述讨论,有入度的强连通分量可以随便选,没有入度的强连通分量 去掉最小的点权的点。剩下贪心取前 k 个就可以了。

进行一次 tarjan的复杂度是 O(n+m),选前 k 个点可以排序一下。这样总复杂 度 O(m+nlogn),期望得分 35 分。注意到复杂度瓶颈在排序上,考虑我们只需要前 k 大而不需要具体前 k 个之间的大小关系,于是使用 std::nth_element()函数可以将复杂度降至 O(n+m)。期望得分 40 分。注意,输入规模到了 10 7 级别,需要 fread 来实现读入优化。

nth_element()函数是一个理论复杂度为O(n)的排序函数(这么6?)

//update 19/11/22(原谅我曾经英语不好)

nth_element这个函数是找第n大的数,把第n大的数放在n的位置上,比起小的放在其左,反之置于其右,不保证有序,算是qsort的一部分,所以这只是用stl实现了qsort中的部分步骤,然后实现了需要排序才能进行查询的事情(其实某种意义上有种数据结构是能实现不排序查询nth大的数的...)

考试总结(CE???)的更多相关文章

  1. 考试T1总结(又CE?!)

    考试T1CE... 最近不适合考试 T1 扶苏是个喜欢一边听古风歌一边写数学题的人,所以这道题其实是五三原题.歌曲中的主人公看着墙边的海棠花,想起当年他其实和自己沿着墙边种了一排海棠,但是如今都已枯萎 ...

  2. Windows Mobile和Wince(Windows Embedded CE)的字符集问题

    背景 开发过Windows Mobile和Wince(Windows Embedded CE)的开发者,特别是Native C++开发者,或多或少都遇到过ANSI字符集和Unicode字符集的转换问题 ...

  3. Linux rhcsa认证考试试题模拟

    声明: 此套试题是2017年rhcsa考试题库,本题库需配合相对应的机器操作,实验环境在我的网盘下载 考试环境: server.group8.example.com 172.24.8.254/24 s ...

  4. [考试反思]1109csp-s模拟测试106:撞词

    (撞哈希了用了模拟测试28的词,所以这次就叫撞词吧) 蓝色的0... 蓝色的0... 都该联赛了还能CE呢... 考试结束前15分钟左右,期望得分300 然后对拍发现T2伪了写了一个能拿90分的垃圾随 ...

  5. [考试反思]1002csp-s模拟测试57:平庸

    一天两场,感觉要完. 不粘排行榜,太壮观了. #1:190 #2:180 #4:160 #35:150 #37:140 #39:120 #kx:20呃... 最后一个是考试结束后了. 又是CE盖40分 ...

  6. [考试反思]0820NOIP模拟测试27:幻影

    注:某让我把“傻孩子”三个字全部删掉了语法不通之处自行脑补(这句本身就语法不通) skyhAK 我和以及milk_feng220 还真的没有考虑过如果我考前3的话这个颜色该怎么表示(自从不粘排行榜以来 ...

  7. [考试反思]0815NOIP模拟测试22

    40分,15名. 1-4:120 75 70 70 35分20名...总之差距极小不想说了 昨天教练说:以后的考试还是联赛知识点,但是难度比联赛高. 没听进去,以为是对于所有人而言的,也就是T1难度变 ...

  8. [考试反思]0813NOIP模拟测试20

    咕了两天,补一下. 4个AK的,210是第10,190的第15并列一大排,我个傻子160排第29. 历史新低,但是心态还好. 真是没想到会一天考两场.中午没回去睡觉晚上考试... 困倒是其次,关键还是 ...

  9. [考试反思]NOIP模拟测试19:洗礼

    []260 []230[]210 []200[8]170[9]160 这套题一般,数据很弱,T1T2暴力都能A,而且都是一些思维题,想不到就爆0. 原因不明,很多一直很强的人在这一次滑铁卢了,于是我个 ...

随机推荐

  1. NSArray和NSMutableArray的常用方法 (转)

    NSArray和NSMutableArray的常用方法 (转) (2013-09-06 15:13:46) 标签: it 分类: ios编程 初始化方法:   1.init返回一个空数组    2.i ...

  2. python partial

    1 很好记忆 partial的第一个参数是函数,后面都是该函数的参数. 2 特殊的地方 partial第一个参数是函数名,但是第二个参数是另外一个函数名. 比如partial(filter, func ...

  3. Codeforces Round #362 (Div. 2) D. Puzzles

    D. Puzzles time limit per test 1 second memory limit per test 256 megabytes input standard input out ...

  4. Aaron Swartz Rewriting Reddit中关于web.py的创建思路

    这天才少年居然自杀了,哎 原文点这 So how should things work? The first principle is that code should be clear and si ...

  5. Android7.0源码编译运行指南【转】

    见连接: http://blog.csdn.net/HardReceiver/article/details/52650303

  6. Bing必应地图中国API入门讲座之八:显示驾车路线

    Bing必应地图中国API入门讲座之八:显示驾车路线 2011-05-24 14:47:36|  分类: Bing&Google|字号 订阅     这篇文章非常值得纪念,因为我是在Googl ...

  7. hdu 5074 Hatsune Miku DP题目

    题目传送门http://acm.hdu.edu.cn/showproblem.php?pid=5074 $dp[i][j] =$ 表示数列前$i$个数以$j$结尾的最大分数 $dp[i][j] = - ...

  8. bzoj 1826 缓存交换

    题目大意: 一些数,需要将他们依次取入一个集合中 集合的容量有限 若该数已经在集合中则不用再取 每次取的时候可以将集合中与元素替换为另一个,也可以不换,直接加入前提是不超过集合容量 求最后最小的取数次 ...

  9. 基于Spark的GBDT + LR模型实现

    目录 基于Spark的GBDT + LR模型实现 数据预处理部分 GBDT模型部分(省略调参部分) GBDT与LR混合部分 基于Spark的GBDT + LR模型实现 测试数据来源http://arc ...

  10. Android网络相关代码

    /** * 获取本机的Ip * * @return */ public String getLocalIpAddress() { try { for (Enumeration<NetworkIn ...