[codeforces]G. Greedy Subsequences
题解: 用单调栈维护右边第一个比他大的元素 把序列转成树形结构 那么对于初始答案就是每个点的深度减1 随着划窗往左 删除一个元素的同时 对这个元素的子树节点的答案减1 这个我们可以用线段树维护$ dfs $序然后做区间修改 加入一个元素时直接单点修改即可 有个小技巧就是把初始线段树初始为$ -inf $ 然后单点修改加上$ inf+deep-1 $就等价于当前节点在删除前面一些元素后的价值 查询全局最大值即可
#include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #include <vector> #include <stack> #include <queue> #include <cmath> #include <set> #include <map> #define mp make_pair #define pb push_back #define pii pair<int,int> #define link(x) for(edge *j=h[x];j;j=j->next) #define inc(i,l,r) for(int i=l;i<=r;i++) #define dec(i,r,l) for(int i=r;i>=l;i--) const int MAXN=1e6+10; const double eps=1e-8; #define ll long long using namespace std; const int inf=1e9; struct edge{int t;edge*next;}e[MAXN<<1],*h[MAXN],*o=e; void add(int x,int y){o->t=y;o->next=h[x];h[x]=o++;} ll read(){ ll x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch))x=x*10+ch-'0',ch=getchar(); return x*f; } int n,k; int a[MAXN],key[MAXN]; int st[MAXN],tot,cnt; int dep[MAXN],p[MAXN],num[MAXN]; void dfs(int x,int pre,int deep){ dep[x]=deep+1;num[x]=1;p[x]=++cnt;key[x]=x; link(x){ dfs(j->t,x,deep+1); num[x]+=num[j->t]; } } int maxx[MAXN<<2],tag[MAXN<<2]; void push(int x){ if(tag[x]){ maxx[x<<1]-=tag[x];maxx[x<<1|1]-=tag[x]; tag[x<<1]+=tag[x];tag[x<<1|1]+=tag[x]; tag[x]=0; } } void up(int x){maxx[x]=max(maxx[x<<1],maxx[x<<1|1]);} void built(int x,int l,int r){ if(l==r){maxx[x]=-inf;return ;} int mid=(l+r)>>1; built(x<<1,l,mid); built(x<<1|1,mid+1,r); up(x); } void update(int x,int l,int r,int ql,int qr){ if(ql<=l&&r<=qr){ tag[x]++;maxx[x]--; return ; } int mid=(l+r)>>1; push(x); if(ql<=mid)update(x<<1,l,mid,ql,qr); if(qr>mid)update(x<<1|1,mid+1,r,ql,qr); up(x); } void update1(int x,int l,int r,int t,int k){ if(l==r){maxx[x]+=k;return ;} int mid=(l+r)>>1; push(x); if(t<=mid)update1(x<<1,l,mid,t,k); else update1(x<<1|1,mid+1,r,t,k); up(x); } int ans[MAXN]; int main(){ n=read();k=read();key[0]=inf; inc(i,1,n)a[i]=read(); dec(i,n,1){ while(tot&&a[st[tot]]<=a[i])tot--; if(!tot)add(n+1,i);else add(st[tot],i); st[++tot]=i; } dfs(n+1,0,0); built(1,1,n+1); dec(i,n,n-k+1)update1(1,1,n+1,p[i],dep[i]-1+inf); ans[n-k+1]=maxx[1]; dec(i,n-k,1){ update(1,1,n+1,p[i+k],p[i+k]+num[i+k]-1); update1(1,1,n+1,p[i+k],-inf); update1(1,1,n+1,p[i],dep[i]+inf-1); ans[i]=maxx[1]; } inc(i,1,n-k+1)printf("%d ",ans[i]); printf("\n"); return 0; }