CF1132G Greedy Subsequences

题目链接:洛谷

题目大意:对于一个长度为$n$的序列$a_i$,它的最长贪心严格上升子序列定义为(1)最长上升子序列(2)对于这个子序列,每个数的后继必须是在原序列中它右边第一个比它大的数。求所有长度为$k$的子区间中,它的最长贪心严格上升子序列的长度。

数据范围:$1\leq k\leq n\leq 10^6,1\leq a_i\leq n$


我们注意到每个数的后继是唯一的,所以可以在数列后面加上一个$n+1$,然后它就是一个树结构。

然后直接用一个单调栈就可以建出来这棵树了。

那么这个最长贪心严格上升子序列的长度就是这个树上的最长链(只能从儿子到父亲)

如果在这个子区间内增加一个$a[x]$,那就是以$x$这个点的子树内的点为起点的最长贪心严格上升子序列都加上1,删除就是减去1。

就用一个线段树维护区间加,区间$\max$就可以了。

 1 #include<bits/stdc++.h>
 2 #define Rint register int
 3 using namespace std;
 4 const int N = 1000003;
 5 int n, k, p[N], stk[N], top, head[N], to[N], nxt[N], dfn[N], siz[N], tim;
 6 inline void add(int a, int b){
 7     static int cnt = 0;
 8     to[++ cnt] = b; nxt[cnt] = head[a]; head[a] = cnt;
 9 }
10 inline void dfs(int x){
11     dfn[x] = ++ tim; siz[x] = 1;
12     for(Rint i = head[x];i;i = nxt[i]) dfs(to[i]), siz[x] += siz[to[i]];
13 }
14 int seg[N << 2], lazy[N << 2];
15 inline void pushdown(int x){
16     if(lazy[x]){
17         seg[x << 1] += lazy[x];
18         seg[x << 1 | 1] += lazy[x];
19         lazy[x << 1] += lazy[x];
20         lazy[x << 1 | 1] += lazy[x];
21         lazy[x] = 0;
22     }
23 }
24 inline void pushup(int x){seg[x] = max(seg[x << 1], seg[x << 1 | 1]);}
25 inline void change(int x, int L, int R, int l, int r, int v){
26     if(l <= L && R <= r){
27         seg[x] += v; lazy[x] += v;
28         return;
29     }
30     int mid = L + R >> 1;
31     pushdown(x);
32     if(l <= mid) change(x << 1, L, mid, l, r, v);
33     if(mid < r) change(x << 1 | 1, mid + 1, R, l, r, v);
34     pushup(x);
35 }
36 int main(){
37     scanf("%d%d", &n, &k);
38     for(Rint i = 1;i <= n;i ++) scanf("%d", p + i);
39     for(Rint i = 1;i <= n;i ++){
40         while(top && p[stk[top]] < p[i]){
41             add(i, stk[top]); -- top;
42         }
43         stk[++ top] = i;
44     }
45     while(top) add(n + 1, stk[top]), -- top;
46     dfs(n + 1);
47     for(Rint i = 1;i <= k;i ++) change(1, 1, n + 1, dfn[i], dfn[i] + siz[i] - 1, 1);
48     printf("%d", seg[1]);
49     for(Rint i = k + 1;i <= n;i ++){
50         change(1, 1, n + 1, dfn[i], dfn[i] + siz[i] - 1, 1);
51         change(1, 1, n + 1, dfn[i - k], dfn[i - k] + siz[i - k] - 1, -1);
52         printf(" %d", seg[1]);
53     }
54 }
View Code

 

转载于:https://www.cnblogs.com/AThousandMoons/p/10624072.html

变分模态分解(Variational Mode Decomposition, VMD)是一种强大的非线性、无参数信号处理技术,专门用于复杂非平稳信号的分析与分解。它由Eckart Dietz和Herbert Krim于2011年提出,主要针对传统傅立叶变换在处理非平稳信号时的不足。VMD的核心思想是将复杂信号分解为一系列模态函数(即固有模态函数,IMFs),每个IMF具有独特的频率成分和局部特性。这一过程与小波分析或经验模态分解(EMD)类似,但VMD通过变分优化框架显著提升了分解的稳定性和准确性。 在MATLAB环境中实现VMD,可以帮助我们更好地理解和应用这一技术。其核心算法主要包括以下步骤:首先进行初始化,设定模态数并为每个模态分配初始频率估计;接着采用交替最小二乘法,通过交替最小化残差平方和以及模态频率的离散时间傅立叶变换(DTFT)约束,更新每个模态函数和中心频率;最后通过迭代优化,在每次迭代中优化所有IMF的幅度和相位,直至满足停止条件(如达到预设迭代次数或残差平方和小于阈值)。 MATLAB中的VMD实现通常包括以下部分:数据预处理,如对原始信号进行归一化或去除直流偏置,以简化后续处理;定义VMD结构,设置模态数、迭代次数和约束参数等;VMD算法主体,包含初始化、交替最小二乘法和迭代优化过程;以及后处理,对分解结果进行评估和可视化,例如计算每个模态的频谱特性,绘制IMF的时频分布图。如果提供了一个包含VMD算法的压缩包文件,其中的“VMD”可能是MATLAB代码文件或完整的项目文件夹,可能包含主程序、函数库、示例数据和结果可视化脚本。通过运行这些代码,可以直观地看到VMD如何将复杂信号分解为独立模态,并理解每个模态的物理意义。 VMD在多个领域具有广泛的应用,包括信号处理(如声学、振动、生物医学信号分析)、图像处理(如图像去噪、特征提取)、金融时间序列分析(识
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值