题意:
给你一些数,定义greedy subsequence:在目标数组为数组c的前提下,构造一个序列p1,p2…pl使得1<=p1,p1<p2,p2<p3…
并且pl<=c的长度,且每个p值要最小,也就是说1 5 2 3 4这个数组,在p1等于1的情况下,p2一定等于2
greedy subsequence就是l的最大值。
现在给你数组a,和一个值k,每次你要做greedy subsequence的区间为i-i+k-1,(1<=i<=n-k+1)
问你每次greedy subsequence的值是多少
题解:
有史以来最快AC的2600,只用了半个小时左右。。
你画一张图就会发现,这个贪心的上升子序列是一棵树,准确的说是一个森林。然后还有最重要的一点,从后往前看,每个点的子树是一个连续的区间。
假设第i个数是x,如果i-1是x-1,那么i-1是x的子树,如果i-1是x+1,那么再往前的数,一定不会连到i,也就是i的子树结束了。
我们首先用树状数组处理出每个点的右边连到哪里,再for一遍处理出每个点的最左端的位置。dfs求出每个点的深度。
那么我们从后往前做,对于每左移一格,右端点的子树的区间-1.用线段树维护区间深度最大值即可。
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
struct node
{
int to,next;
}e[N];
int cnt,head[N];
void add(int x,int y)
{
e[cnt].to=y;
e[cnt].next=head[x];
head[x]=cnt++;
}
struct Array_Tree
{
int mi[N];
int lowbit(int x){return x&(-x);}
void add(int x,int v)
{
for(int i=x;i;i-=lowbit(i))
mi[i]=min(mi[i],v);
}
int query(int x)
{
int ans=N;
for(int i=x;i<N;i+=lowbit(i))
ans=min(ans,mi[i]);
return ans;
}
}t1;
struct Line_Tree
{
int mx[N*4],flag[N*4],dep[N];
void dfs(int x,int fa)
{
dep[x]=dep[fa]+1;
for(int i=head[x];~i;i=e[i].next)
{
int ne=e[i].to;
dfs(ne,x);
}
}
void push_down(int root)
{
if(!flag[root])return ;
mx[root<<1]+=flag[root];
mx[root<<1|1]+=flag[root];
flag[root<<1]+=flag[root];
flag[root<<1|1]+=flag[root];
flag[root]=0;
}
void build(int l,int r,int root)
{
if(l==r)
{
mx[root]=dep[l];
return ;
}
int mid=l+r>>1;
build(l,mid,root<<1);
build(mid+1,r,root<<1|1);
mx[root]=max(mx[root<<1],mx[root<<1|1]);
}
void update(int l,int r,int root,int ql,int qr,int v)
{
if(l>=ql&&r<=qr)
{
mx[root]+=v;
flag[root]+=v;
return ;
}
push_down(root);
int mid=l+r>>1;
if(mid>=ql)
update(l,mid,root<<1,ql,qr,v);
if(mid<qr)
update(mid+1,r,root<<1|1,ql,qr,v);
mx[root]=max(mx[root<<1],mx[root<<1|1]);
}
int query(int l,int r,int root,int ql,int qr)
{
if(l>=ql&&r<=qr)
return mx[root];
push_down(root);
int mid=l+r>>1,ans=0;
if(mid>=ql)
ans=query(l,mid,root<<1,ql,qr);
if(mid<qr)
ans=max(ans,query(mid+1,r,root<<1|1,ql,qr));
return ans;
}
}t2;
int a[N],le[N],ans[N],pre[N];
vector<int>vec;
int main()
{
memset(head,-1,sizeof(head));
int n,k;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
for(int i=1;i<N;i++)t1.mi[i]=N,le[i]=i;
for(int i=n;i>=1;i--)
{
int p=t1.query(a[i]+1);
if(p==N)
vec.push_back(i);
else
add(p,i),le[p]=i,pre[i]=p;
t1.add(a[i],i);
}
for(int i=1;i<=n;i++)le[pre[i]]=min(le[pre[i]],le[i]);
for(auto i:vec)t2.dfs(i,0);
t2.build(1,n,1);
for(int i=n-k+1;i>=1;i--)
{
ans[i]=t2.query(1,n,1,i,i+k-1);
t2.update(1,n,1,le[i+k-1],i+k-1,-1);
}
for(int i=1;i<=n-k+1;i++)
printf("%d%c",ans[i]," \n"[i==n-k+1]);
return 0;
}