听说,一个好的Oier都是题目喂出来的。

题目

定义一个序列的最长贪心严格上升子序列为:若选出的子序列为 \(a\),对于其中相邻两项 \(i,j\),不存在 b\(i<k<j\),满足在原序列 \(b\) 中,有 \(b_i<b_k\),换句话说就是选择一个元素后必须选择它之后第一个大于它的元素

给定一个长度为 \(n\) 的序列,同时给定一个常数 \(k\),求该序列的所有长度为 \(k\)的子区间的最长贪心严格上升子序列的长度

数据范围\(10^6\)

解题思路

先想了一个长链剖分的假做法,发现不会处理长儿子,自闭了。

考虑每个点的出度都不超过1,所以他构成了一颗森林

设\(f_x\)表示从x开始往上走,最长走多远。

每加入一个点,需要把它的子树内的所有点权值+1

每删除一个点,需要把它的权值变得足够小

线段树维护即可

代码

#include<bits/stdc++.h>
#define now edge[i].v
#define go(x) for(int i=head[x];i;i=edge[i].nxt)
#define ls o<<1,l,mid
#define rs o<<1|1,mid+1,r
using namespace std;
const int sz=1e6+527;
int n,k;
int cnt,T;
int x,y,z;
int head[sz];
int a[sz],ans[sz];
int dfn[sz],lev[sz];
stack<int>s;
struct Edge{
int v,nxt;
}edge[sz];
struct node{
int tag,mx;
}tr[sz<<2];
void add(int u,int v){
edge[++cnt]=(Edge){v,head[u]};
head[u]=cnt;
}
void update(int o){
tr[o<<1].tag+=tr[o].tag;
tr[o<<1|1].tag+=tr[o].tag;
tr[o<<1].mx+=tr[o].tag;
tr[o<<1|1].mx+=tr[o].tag;
tr[o].tag=0;
}
void modify(int o,int l,int r){
if(x<=l&&r<=y) return (void)(tr[o].mx+=z,tr[o].tag+=z);
if(tr[o].tag) update(o);
int mid=(l+r)>>1;
if(x<=mid) modify(ls);
if(y>mid) modify(rs);
tr[o].mx=max(tr[o<<1].mx,tr[o<<1|1].mx);
}
void dfs(int x){
dfn[x]=++T;
go(x)
dfs(now);
lev[x]=T;
}
int main(){
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
while(!s.empty()&&a[s.top()]<a[i]){
add(i,s.top());
s.pop();
}
s.push(i);
}
n++;
while(!s.empty()){
add(n,s.top());
s.pop();
}
dfs(n);
for(int i=1;i<=k;i++){
x=dfn[i],y=lev[i],z=1;
modify(1,1,n);
}
ans[1]=tr[1].mx;
for(int i=k+1;i<n;i++){
x=dfn[i],y=lev[i],z=1;
modify(1,1,n);
x=dfn[i-k],y=lev[i-k],z=-1;
modify(1,1,n);
ans[i-k+1]=tr[1].mx;
}
for(int i=1;i<=n-k;i++) printf("%d ",ans[i]);
}

题目链接

CF1132G的更多相关文章

  1. [CF1132G]Greedy Subsequences

    [CF1132G]Greedy Subsequences 题目大意: 定义一个序列的最长贪心严格上升子序列为:任意选择第一个元素后,每次选择右侧第一个大于它的元素,直到不能选为止. 给定一个长度为\( ...

  2. 【CF1132G】Greedy Subsequences(线段树)

    [CF1132G]Greedy Subsequences(线段树) 题面 CF 题解 首先发现选完一个数之后选择下一个数一定是确定的. 对于每个数预处理出左侧第一个比他大的数\(L\),那么这个数加入 ...

  3. cf1132G. Greedy Subsequences(线段树)

    题意 题目链接 Sol 昨天没想到真是有点可惜了. 我们考虑每个点作为最大值的贡献,首先预处理出每个位置\(i\)左边第一个比他大的数\(l\),显然\([l + 1, i]\)内的数的后继要么是\( ...

  4. cf1132G 线段树解分区间LIS(一种全新的线段树解LIS思路)+单调栈

    /* 给定n个数的数列,要求枚举长为k的区间,求出每个区间的最长上升子序列长度 首先考虑给定n个数的数列的LIS求法:从左往右枚举第i点作为最大点的贡献, 那么往左找到第一个比a[i]大的数,设这个数 ...

随机推荐

  1. 01.visual studio 2017添加菜单

    创建项目 文件--新建项目 如果新建项目 左侧没有扩展菜单,请安装即可 添加菜单 右键--添加新项 菜单设置 菜单设置文件: MyCommandPackage.vsct <Buttons> ...

  2. mvvmlight下passwordBox绑定的解决方法

    在做公司的项目中,用到MVVMLight框架,需要做登陆注册的功能模块,但是在wpf中passwordBox没有内置绑定功能,因为出于安全的考虑.但是,博主又非常想要契合mvvm思想,一定要passw ...

  3. Luogu P3496 [POI2010]GIL-Guilds(贪心+搜索)

    P3496 [POI2010]GIL-Guilds 题意 给一张无向图,要求你用黑(\(K\))白(\(S\))灰(\(N\))给点染色,且满足对于任意一个黑点,至少有一个白点和他相邻:对于任意一个白 ...

  4. dump与load

    dump与load 简化了dumps与loads

  5. anime.js 学习笔记

    官网演示/文档 anime.js 是一个简便的JS动画库,用法简单而且适用范围广,涵盖CSS,DOM,SVG还有JS的对象,各种带数值属性的东西都可以动起来. 实际演示和代码,官网写得很详细清楚了,这 ...

  6. 19.10.14-Q

    小$P$的咕事 总结: 还行,就是$T1$写的慢了,$T2,T3$暴力有点锅 T1 小模拟. 打就是了. 可以小小的手玩一下. (考试的时候某同志人肉对拍了$20min$)=.= 418 ms 360 ...

  7. svn里update以后还是有红色的感叹号怎么办

    不用那么麻烦,直接还原就行了,客户端是TortoiseSVN的话,在该文件或文件夹上点右键,选择TortoiseSVN——revert有时还原之后系统反应没那么快,还是显示红色感叹号,刷新几下就正常了 ...

  8. centos yum 坏掉 db 损坏

    #首先清除掉缓存,之后再重建就可以了 rm -f /var/lib/rpm/__db* rpm --rebuilddb 提示的错误应该是: error: rpmdb: BDB0113 Thread/p ...

  9. 009-python一些问题整理

    1. Python中的 // 与 / 的区别 " / "  表示浮点数除法,返回浮点结果 >>> 90/30 3.0 " // " 表示整数除 ...

  10. mysql知识点回顾与梳理

    一.sql语句执行顺序 from join on where group by avg,sum,count等各种函数 having select distinct order by(asc(升序),d ...