为了能到远方,脚下的每一步都不能|

Creeper_l

园龄:1年4个月粉丝:10关注:13

P8125 [BalticOI 2021 Day2] The short shank 题解

首先会发现若 \(t_i <= T\) 的话那么他最终一定会造反。

我们只考虑 \(t_i >T\) 的情况。设 \(lst_i\) 表示 \(i\) 左边第一个可以影响(使他造反)到 \(i\) 的位置,那么我们一定要在 \([lst_i,i]\) 这个区间中的某一个位置放上床垫才能使 \(i\) 不造反。

这样有一个 \(O(nd)\) 的 dp,但是复杂度显然会炸。考虑挖掘一些性质,会发现所有区间都是包含或者不交的。证明也比较简单,若两个区间有交,即 \(i<j,lsti \le lst_j \le i\),那么 \(lst_j\) 这个位置也一定能影响到 \(i\),矛盾。所以任意两个区间都不交叉。

那么我们按照区间的包含关系建图,就变成了一个森林。考虑转化题意,若在叶子节点的区间中放一个床垫,那么它到根节点的路径上的所有点都不会造反了。所以题意转化为求 \(d\) 条不相交的链,使得这些链的总长度最大。这个问题直接长链剖分,然后取前 \(d\) 长的链即可。

\(lst\) 数组以及连边都可以用单调栈维护,最终求前 \(d\) 长链可以用优先队列维护,时间复杂度 \(O(n+d \log n)\)

关于取前 \(d\) 长的链的简单证明:对于两条不是最长链的链,我们都可以把它换成最长链加另外一条链,这样总长度一定不劣(画个图更容易理解)。

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 2e6 + 10;
int n,d,T,t[MAXN],lst[MAXN],ans,fa[MAXN];
int head[MAXN],cnt,depth[MAXN],son[MAXN],mx[MAXN];
struct Node {int u,v,nxt;}e[MAXN << 1];
void Add(int u,int v) {e[++cnt] = {u,v,head[u]};head[u] = cnt;}
priority_queue <int,vector <int>,less <int> > q;
void dfs(int u,int father) {
	depth[u] = depth[father] + 1,mx[u] = depth[u];
	for(int i = head[u]; ~ i;i = e[i].nxt) {
		int now = e[i].v;
		if(now == father) continue;
		dfs(now,u),mx[u] = max(mx[u],mx[now]);
		if(mx[now] > mx[son[u]]) son[u] = now;
	}
} void sdfs(int u,int father,int len) {
	if(son[u] == 0) return q.push(len);
	sdfs(son[u],u,len + 1);
	for(int i = head[u]; ~ i;i = e[i].nxt) 
		if(e[i].v != father && e[i].v != son[u]) sdfs(e[i].v,u,1);
} stack <int> s;
signed main() {
	memset(head,-1,sizeof head);
	cin >> n >> d >> T;
	for(int i = 1;i <= n;i++) cin >> t[i];
	for(int i = 1;i <= n;i++) 
		if(t[i] > T) {
			while(s.size() && t[s.top()] + i - s.top() > T) s.pop(); 
			if(s.size()) lst[i] = s.top();
		} else {
			while(s.size() && t[s.top()] + i - s.top() >= t[i]) s.pop(); 
			s.push(i);
		}
	while(!s.empty()) s.pop();
	for(int i = n;i >= 1;i--) {
		if(lst[i] == 0) continue;
		while(!s.empty() && lst[s.top()] > lst[i]) s.pop();
		if(!s.empty()) Add(s.top(),i),fa[i] = s.top();
		s.push(i); 
	} for(int i = 1;i <= n;i++) {
		if(t[i] <= T) continue;
		if(lst[i] == 0) ans++;
		else if(fa[i] == 0) dfs(i,0),sdfs(i,0,1);
	} while(d > 0 && !q.empty()) 
		ans += q.top(),q.pop(),d--; 
	cout << n - ans;
	return 0;
} 

本文作者:Creeper_l

本文链接:https://www.cnblogs.com/Creeperl/p/18232680

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Creeper_l  阅读(10)  评论(0编辑  收藏  举报
  1. 1 イエスタデイ(翻自 Official髭男dism) 茶泡饭,春茶,kobasolo
  2. 2 世间美好与你环环相扣 柏松
  3. 3 True love tired
  4. 4 一笑江湖 (DJ弹鼓版) 闻人听書_
  5. 5 最好的安排 曲婉婷
  6. 6 星星在唱歌 司南
  7. 7 山川 李荣浩
  8. 8 On My Way Alan Walker
  9. 9 百战成诗 王者荣耀·100英雄官方群像献礼歌
  10. 10 雪 Distance Capper / 罗言
  11. 11 Edamame bbno$ / Rich Brian
  12. 12 半生雪 七叔-叶泽浩
  13. 13 Catch My Breath Kelly Clarkson
  14. 14 Love Is Gone SLANDER / Dylan Matthew
  15. 15 Endless Summer Alan Walker / Zak Abel
  16. 16 悬溺 葛东琪
  17. 17 风吹丹顶鹤 葛东琪
  18. 18 Normal No More TYSM
  19. 19 哪里都是你 队长
  20. 20 Stronger Kelly Clarkson
  21. 21 廖俊涛
  22. 22 消愁 毛不易
  23. 23 The Runner Yubik
  24. 24 踏山河 七叔-叶泽浩
  25. 25 Waiting For Love Avicii
  26. 26 在你的身边 盛哲
  27. 27 Dream It Possible Delacey
  28. 28 凄美地 郭顶
  29. 29 满天星辰不及你 ycc
  30. 30 侧脸 于果
  31. 31 阿拉斯加海湾 蓝心羽
  32. 32 虞兮叹 闻人听書_
  33. 33 离别开出花 就是南方凯
  34. 34 盗墓笔记·十年人间 李常超 (Lao乾妈)
The Runner - Yubik
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起