直接开写题解:

(由于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. 使用mpxj读取MSPrjoect

    import java.util.ArrayList; import java.util.Calendar; import java.util.Hashtable; import java.util. ...

  2. HDU 5475An easy problem 离线set/线段树

    An easy problem Time Limit: 8000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) ...

  3. 【bzoj4245】[ONTAK2015]OR-XOR

    利用前缀和选m个区间等价于选m个数 从最高位开始找,如果这一位至少有m个0,则可以为0,该位为1的后面就不可以选了. 还要注意,最后一个数如果该位为1,那么这一位必须为1,然后要从62开始枚举,而不是 ...

  4. linux用于文件解压缩的命令

    1 gzip gzip -<压缩率> 压缩率用数字(1-9)来表示,越大,则压缩率越大. 2 bz2 解压bz2 bzip2 -d filename.bz2

  5. Python中关键字global与nonlocal的区别

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/xCyansun/article/details/79672634终于下定决心学习Python了.既然 ...

  6. POJ1704 Georgia and Bob Nim游戏

    POJ1704 这道题可以转化为经典的Nim游戏来解决. Nim游戏是这样的 有n堆石子,每堆各有ai个. 两个人轮流在任意石子堆中取至少1个石子,不能再取的输. 解决方法如下, 对N堆石子求异或 为 ...

  7. Linux-----Kconfig文件的简介

    内核源码树的目录下都有两个文件Kconfig和Makefile.分布到各目录的Kconfig构成了一个分布式的内核配置数据库, 每个Kconfig分别描述了所属目录源文件相关的内核配置菜单.在内核配置 ...

  8. 常用开源<监控软件>介绍

    转载地址:http://blog.csdn.net/lx_9986/article/details/6803243 一.Zenoss Core Zenoss Core是开源企业级IT管理软件-是智能监 ...

  9. ubuntu/linuxmint如何添加和删除PPA源

    [添加] 1.sudo add-apt-repository ppa:user/ppa-name 2.sudo apt-get update (然后再安装软件sudo apt-get install ...

  10. 如何过滤 adb logcat 输出(转载)

    转自:http://www.cnblogs.com/imouto/archive/2012/12/11/filtering-adb-logcat-output.html 简介: 本文介绍如何在 she ...