题目

传送门 to CF

思路

首先第一步就把我难倒了:建树。我连树都建不出来,还要我在树上求解问题?吔屎啦你!

当然仔细想想,二叉搜索树实际上是 用树中已存在的节点的值,将值域分割了。对吧?每个点作为分界线,大于它和小于它的,一定不在同一个子树内。反之,若两个点不在同一个子树内,那么存在一个点作为分界线。

那么更进一步,某个叶节点的父节点一定是它的前驱,或者后继。这也是毫无疑问的,从求前驱后继的过程就能得知了。

于是我们有一种简单但是实用的建树方式:用 s e t \rm set set 维护目前所有点的值,加入一个点的时候,查询它的前驱后继,谁没有对应的儿子,当前点就可以当儿子。

建树讲完了。接下来的工作反而简单。 i n s e r t \rm insert insert 顺序可以任意调整,听上去很恐怖吗?只需要考察相邻的两个数交换。显然如果二者不是父亲儿子关系,就没有任何影响。如果是父子关系,二者就会进行一个平衡树中的 r o t a t e \rm rotate rotate 操作。

很容易推广:对于特殊点(在区间 [ L , R ] [L,R] [L,R] 内的数)构成的连通块,可以任意 r o t a t e \rm rotate rotate 。直观地想,也挺容易理解的。当然两个连通块之间不存在祖先关系。

仍然用到上面对于 B S T \tt BST BST 的思考。特殊点无论怎么转,总是割出 s i z e + 1 size+1 size+1 个区间,并且每个区间内包含的数字是固定的。任意两个相邻区间可以是兄弟节点。所以问题变成了一个 H u f f m a n \it{Huffman} Huffman 编码的问题,只不过兄弟节点必须相邻。

这玩意儿就不那么容易贪心了。同样可以证明,权值最小的点必然是直接与旁边某个点作为兄弟节点。然而究竟是左还是右呢?严厉抨击左倾思想!

考虑到 R − L + 1 ⩽ 200 R-L+1\leqslant 200 R−L+1⩽200,也就是说最多 201 201 201 个点,那就直接区间 d p \tt dp dp 好了呗!

时间复杂度 O [ n log ⁡ n + ( R − L ) 3 ] \mathcal O[n\log n+(R-L)^3] O[nlogn+(R−L)3] 。当然对于前面这部分,就有说法了,即插入顺序本质上就是影响父子关系的。对于插入时间而言,满足小根堆性质。所以我们只需要按照普通的笛卡尔树 O ( n ) \mathcal O(n) O(n) 单调栈建树!可惜需要先按照权值排序,没能跃入线性。

代码

#include <cstdio>
#include <iostream>
#include <cstring>
#include <vector>
#include <algorithm>
#include <set>
using namespace std;
# define rep(i,a,b) for(int i=(a); i<=(b); ++i)
# define drep(i,a,b) for(int i=(a); i>=(b); --i)
typedef long long int_;
inline int readint(){int a = 0; char c = getchar(), f = 1;for(; c<'0'||c>'9'; c=getchar())if(c == '-') f = -f;for(; '0'<=c&&c<='9'; c=getchar())a = (a<<3)+(a<<1)+(c^48);return a*f;
}const int MaxN = 100005;
int ch[MaxN][2], dep[MaxN], siz[MaxN];
void getInfo(int x){if(!x) return ;rep(j,(siz[x]=1)^1,1){getInfo(ch[x][j]);siz[x] += siz[ch[x][j]];}
}int_ ans; bool vis[MaxN];
void sumDep(int x){if(!x) return ;ans += dep[x]; vis[x] = 1;rep(j,0,1) sumDep(ch[x][j]);
}vector<int> v;
bool good[MaxN]; // if it's special
void collect(int x){if(!x) return v.push_back(0);if(!good[x]){v.push_back(siz[x]);ans -= 1ll*dep[x]*siz[x];return sumDep(x);}vis[x] = true;rep(j,0,1) collect(ch[x][j]);
}const int MaxM = 205;
const int infty = (1<<30)-1;
int dp[MaxM][MaxM], pre[MaxM];
int solve(){int len = int(v.size())-1;for(int i=1; i<=len; ++i)pre[i] = pre[i-1]+v[i];drep(i,len,1) rep(j,i+1,len){dp[i][j] = infty;rep(k,i,j-1){int t = dp[i][k]+dp[k+1][j];dp[i][j] = min(dp[i][j],t);}dp[i][j] += pre[j]-pre[i-1]+j-i-1;}return dp[1][len];
}set<int> s; int a[MaxN];
int main(){int n = readint();s.insert(n+1); // guards.insert(a[1] = readint());for(int i=2; i<=n; ++i){a[i] = readint();auto fa = s.lower_bound(a[i]);if((*fa) <= n && !ch[*fa][0])ch[*fa][0] = a[i];else ch[*(--fa)][1] = a[i];dep[a[i]] = dep[*fa]+1;s.insert(a[i]); // important!}getInfo(a[1]); // scanint l = readint(), r = readint();rep(i,l,r) good[a[i]] = 1;for(int i=l; i<=r; ++i){if(vis[a[i]]) continue;v.resize(1); // guardcollect(a[i]), ans += solve();ans += 1ll*siz[a[i]]*dep[a[i]];}for(int i=1; i<=n; ++i)if(!vis[i])ans += dep[i];printf("%lld\n",ans+n);return 0;
}

后记

我当时还有一个神奇的想法。先随意地将二叉平衡树建出来,然后用 S p l a y \tt Splay Splay 将每个点依次转上去!

这样可以支持在线查询,好诶!

[CF_GYM102798K]Tree Tweaking相关推荐

  1. 三分钟基础:路由器是如何偷偷植入广告的?

    程序员的成长之路 互联网/程序员/成长/职场 关注 阅读本文大概需要 5 分钟. 来源:编程技术宇宙 作者:轩辕之风 1 捞油水 "今天的工作累死了,这好色的人类看了这么多视频,可把我忙的够 ...

  2. 2020CCPC威海

    2020CCPC威海 2020CCPC威海榜单 题号 题目 知识点 难度 A Golden Spirit 思维,推导题 签到题 B Labyrinth dfs+思维 金牌题 C Rencontre D ...

  3. 107. Binary Tree Level Order Traversal II

    题目 Given a binary tree, return the bottom-up level order traversal of its nodes' values. (ie, from l ...

  4. 102. Binary Tree Level Order Traversal

    题目 Binary Tree Level Order Traversal 层次遍历二叉树 链接 Given a binary tree, return the level order traversa ...

  5. Python---哈夫曼树---Huffman Tree

    今天要讲的是天才哈夫曼的哈夫曼编码,这是树形数据结构的一个典型应用. !!!敲黑板!!!哈夫曼树的构建以及编码方式将是我们的学习重点. 老方式,代码+解释,手把手教你Python完成哈夫曼编码的全过程 ...

  6. [Java]LeetCode297. 二叉树的序列化与反序列化 | Serialize and Deserialize Binary Tree

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★ ➤微信公众号:山青咏芝(shanqingyongzhi) ➤博客园地址:山青咏芝(https://www.cnblog ...

  7. Code Forces Bear and Forgotten Tree 3 639B

    B. Bear and Forgotten Tree 3 time limit per test2 seconds memory limit per test256 megabytes inputst ...

  8. Codeforces Round #417:E. FountainsSagheer and Apple Tree(树上博弈)

    Codeforces Round #417:E. FountainsSagheer and Apple Tree(树上博弈) 标签: codeforces 2017-06-02 11:41 29人阅读 ...

  9. datagrid底部显示水平滚动_DevExpress WPF v19.1:Data Grid/Tree List等控件功能增强

    行业领先的.NET界面控件DevExpress 日前正式发布v19.1版本,本站将以连载的形式介绍各版本新增内容.在本系列文章中将为大家介绍DevExpress WPF v19.1中新增的一些控件及部 ...

最新文章

  1. js中push和pop的用法
  2. jvm:类加载器与双亲委派模型
  3. leetcode 598. Range Addition II | 598. 范围求和 II
  4. 面向对象命名空间、组合
  5. python执行shell命令、并获取执行过程信息_python执行使用shell命令方法
  6. Jetty9 源码初解(2)——IO之Connection
  7. IT职场健康杀手与应对宝典 (虽然是IT职场,可是对于常上网的ggmm也是很有用的)...
  8. java cropper 上传_java web 网站头像上传处理 (springmvc +bootstrap+cropper)
  9. ansible中的file、cron、debug、template、lineinfile、blockinfile模块的介绍和使用
  10. python selenium span_如何使用selenium从span获取文本
  11. Machine Learning笔记——逻辑回归算法
  12. Linux .swp文件恢复
  13. 专业技术计算机应用能力考试ppt2007,全国专业技术人员计算机应用能力考试PPT题库.pdf...
  14. 做软文营销发布有哪些常见平台?
  15. MATLAB图像融合分割系统
  16. 星淘惠:现在做跨境电商还有优势吗?跨境电商发展怎么样
  17. 【Navicat】Navicat Premium12 下载、安装、激活、过期解决方法 —— 永久有效
  18. hdu2795 线段树应用:找到线段树中=给定值的第一个元素位置 并 更新该点)
  19. 天池-金融风控训练营-task5-模型融合
  20. tesla k80显卡 配置支持opengl

热门文章

  1. 中拓互联解密:一个购物码,可以玩出什么花样?
  2. 《ChineseBERT: Chinese Pretraining Enhanced by Glyph and Pinyin Information》阅读记录
  3. 为什么要新零售 新零售的“人、货、场”需要哪些变化?
  4. 3秒了解Ajax数据交互
  5. 图书管理系统测试报告--信息管理功能篇
  6. 电脑开机黑屏不显示任何东西 电脑黑屏什么都不显示怎么回事
  7. 方舟服务器网络信息错误,明日方舟网络安全配置初始化失败请重试\n错误号-1解决办法...
  8. OpenOCD学习笔记 3-配置基本知识
  9. 编写猫咪相册应用 HTML
  10. Java 读取文件全部内容