前言

题目链接:洛谷

题意简述

一棵有根树,节点数 \(n \leq 10^5\),每个点有权值 \(v_i \leq 2000\),现在选出一些点,满足:

  1. 一个点的父亲点若未被选择则其不能被选择。
  2. 所选点的集合内不能有相同的权值。
  3. 对于每一个选择的点,其子树中所有被选择点的权值必须可以构成公差为 \(1\) 的等差数列。

求满足上述条件构成的等差数列的方案数。

题目分析

凭直觉是树形 DP。考虑记 \(f[i][l][r]\) 表示在 \(i\) 子树,\(i\) 必选,能否构成 \(l \sim r\) 的等差数列。发现有冗余状态,即由于 \(i\) 必选,一定有 \(l \leq v_i \leq r\),其他状态是不合法的。

进一步发现,对于 \(yzh \in \operatorname{son}(i)\),她对 \(i\) 的贡献要么全在 \(v_i\) 左边,要么全在右边,否则会因为已经选中了一个权值为 \(v_i\) 的点不符合要求。进一步发现,如果 \(v_{yzh} < v_i\),她只能贡献左边,反之如果 \(v_{yzh} > v_i\) 贡献右边。即 \(yzh\) 不会对 \(i\) 两边都产生贡献。

所以将状态砍半,记 \(L[i][l]\) 和 \(R[i][r]\) 分别表示在 \(i\) 子树,\(i\) 必选,能否构成 \(l \sim v_i\) 的等差数列或 \(v_i \sim r\) 的等差数列。边界为 \(L[i][v_i] = R[i][v_i] = \text{true}\)。由于讨论过一个孩子不可能对左右多产生贡献,所以 \(L\) 和 \(R\) 是独立的,答案就是乘法原理,\(L[1]\) 中为 \(\text{true}\) 的个数与 \(R[1]\) 中为 \(\text{true}\) 的个数之积即为答案。

说了这么多,考虑转移。考虑 \(v_{yzh} < v_i\) 的情况,反之同理。如果存在一个值 \(k\),满足在 \(yzh\) 中能够得到 \(v_{yzh} \sim k\),并且在之前的 \(i\) 中能够得到 \(k + 1 \sim v_i\),那么,就可以把 \(L[yzh]\) 或到 \(L[i]\) 上。需要注意的是,转移的顺序也要考虑。即我们要先考虑 \(v_{yzh}\) 靠近 \(v_i\) 的孩子,这样后续可能会使用到这次更新过来的信息。

时间复杂度:\(\Theta(n(V + \log n))\),如果使用 bitset 优化,则是:\(\Theta(\cfrac{nV}{w} + n \log n)\)。

代码

// #pragma GCC optimize(3)
// #pragma GCC optimize("Ofast", "inline", "-ffast-math")
// #pragma GCC target("avx", "sse2", "sse3", "sse4", "mmx")
#include <iostream>
#include <cstdio>
#define debug(a) cerr << "Line: " << __LINE__ << " " << #a << endl
#define print(a) cerr << #a << "=" << (a) << endl
#define file(a) freopen(#a".in", "r", stdin), freopen(#a".out", "w", stdout)
#define main Main(); signed main() { return ios::sync_with_stdio(0), cin.tie(0), Main(); } signed Main
using namespace std; #include <algorithm>
#include <vector>
#include <bitset> int n, val[100010];
vector<int> edge[100010];
bitset<2010> L[100010], R[100010]; void dfs(int now) {
L[now][val[now]] = R[now][val[now]] = 1;
for (const auto& to: edge[now]) dfs(to);
for (int i = 0; i < (int)edge[now].size(); ++i) {
int to = edge[now][i];
if (val[to] > val[now]) {
if (((R[now] << 1) & L[to]).any()) {
R[now] |= R[to];
}
}
}
for (int i = (int)edge[now].size() - 1; i >= 0; --i) {
int to = edge[now][i];
if (val[to] < val[now]) {
if (((L[now] >> 1) & R[to]).any()) {
L[now] |= L[to];
}
}
}
} signed main() {
scanf("%d", &n);
for (int i = 1; i <= n; ++i) scanf("%d", &val[i]);
for (int i = 1, u, v; i <= n - 1; ++i) {
scanf("%d%d", &u, &v);
edge[u].push_back(v);
}
for (int i = 1; i <= n; ++i)
sort(edge[i].begin(), edge[i].end(), [] (const int &a, const int &b) {
return val[a] < val[b];
});
dfs(1);
printf("%llu", L[1].count() * R[1].count());
return 0;
}

[COCI2015-2016#1] UZASTOPNI 题解的更多相关文章

  1. P6666 [清华集训2016] 数据交互 题解

    ## P6666 [清华集训2016] 数据交互 题解 ### 简要题意: n个点的树,m次操作,分别为添加一条路径$(u_i,v_i,w_i)$,和撤消一条路径,每一次操作后求出一条路径使得与这条路 ...

  2. [COCI]coci2015/2016 nekameleoni

    题意: 初始数列,每个数都在1~k以内 支持两种操作:1.修改一个数,修改后的数在1~k内                           2.查询一个最短包含1~k的序列的长度 查询100000 ...

  3. COCI 2015、2016 1st round 题解(官方)

    官方题解: 官方代码: Code-KARTE: #include <cstdio> #include <iostream> #include <cstring> u ...

  4. CODE FESTIVAL 2016 Grand Final 题解

    传送门 越学觉得自己越蠢--这场除了\(A\)之外一道都不会-- \(A\) 贪心从左往右扫,能匹配就匹配就好了 //quming #include<bits/stdc++.h> #def ...

  5. noip 2016 提高组题解

    前几天写的那个纯属搞笑.(额,好吧,其实这个也不怎么正经) 就先说说day2吧: T1:这个东西应该叫做数论吧. 然而我一看到就照着样例在纸上推了大半天(然而还是没有看出来这东西是个杨辉三角) 然后就 ...

  6. NCPC 2016:简单题解

    A .Artwork pro:给定N*M的白色格子,然后Q次黑棒,输出每次加黑棒后白色连通块的数量.(N,M<1e3, Q<1e4) sol:倒着离线做,并查集即可. (在线做法:http ...

  7. 2016 ACM-ICPC EC-Final题解

    题目链接 A. Number Theory Problem 题意:给你一个数N,求形如2k-1且小于2N的数中有多少能被7整除. 解法:观察二进制位找规律,答案是N/3. #include<bi ...

  8. NOIP 2016 组合数问题 题解

    一道sb题目,注意范围,可打表解决,打出杨辉三角,在用前缀和求解即可 代码(一维前缀和) #include<bits/stdc++.h> using namespace std; int ...

  9. CODE FESTIVAL 2016 qual C题解

    传送门 \(A\) 什么玩意儿-- const int N=105; char s[N];int n,f1,f2; int main(){ scanf("%s",s+1),n=st ...

  10. CODE FESTIVAL 2016 qual B题解

    传送门 \(A\) 什么玩意儿-- const char t[]={"0CODEFESTIVAL2016"}; char s[25];int res; int main(){ sc ...

随机推荐

  1. 引入feign注入报错 org.springframework.beans.factory.NoSuchBeanDefinitionException解决

    引入feign注入报错 org.springframework.beans.factory.NoSuchBeanDefinitionException解决 [172.16.22.215] out: C ...

  2. 认真学习CSS3-问题收集-102号-关于定位

    css中有关于定位的一个属性position. 在w3cschool中,position的介绍如下: 值 描述 absolute 生成绝对定位的元素,相对于 static 定位以外的第一个父元素进行定 ...

  3. yum update和yum upgrade的区别

    看见网上很多关于这个问题的解答,但是大部分都是错的,误人子弟! 很多都是执行这两个命令,然后查看系统的变化.看似严谨,实则愚蠢至极. 就算不懂内核,也应该懂得什么是内核呀!也应该懂得内核是怎么进入的啊 ...

  4. Vue3 中的 v-bind 指令:你不知道的那些工作原理

    前言 v-bind指令想必大家都不陌生,并且都知道他支持各种写法,比如<div v-bind:title="title">.<div :title="t ...

  5. 35个Redis企业级性能优化点与解决方案

    Redis作为企业级应用中广泛使用的高性能键值存储数据库,其性能优化是一个复杂且多面的话题.以下是V 哥整理的一些关键的优化点和相应的解决方案,提供给兄弟们参考. Redis的性能优化涉及到硬件选择. ...

  6. dense并行训练1-流水线并行

    并行训练-流水线 简述 并行训练主要有三种策略: 数据并行训练加速比最高,但要求每个设备上都备份一份模型,显存占用比较高,但缺点是通信量大. 张量并行,通信量比较高,适合在机器内做模型并行. 流水线并 ...

  7. 前端 Array.sort() 源码学习

    源码地址 V8源码Array 710行开始为sort()相关 Array.sort()方法是那种排序呢? 去看源码主要是源于这个问题 // In-place QuickSort algorithm. ...

  8. QT学习:00 介绍

    --- title: framework-cpp-qt-00-介绍 date: 2020-04-08 15:41:54 categories: tags: - c/c++ - qt --- 章节描述: ...

  9. 【论文阅读】TRO 2021: Fail-Safe Motion Planning for Online Verification of Autonomous Vehicles Using Convex Optimization

    参考与前言 Last edited time: August 3, 2022 10:04 AM Status: Reading Type: TRO Year: 2021 论文链接:https://ie ...

  10. NKCTF 2023 Misc

    NKCTF 2023 Misc hard-misc base32 --> N0wayBack公众号回复:NKCTF2023我来了! 得到flag:NKCTF{wtk2023Oo0oImcoM1N ...