[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;
}

 

posted @ 2019-03-06 04:53  wang9897  阅读(327)  评论(0编辑  收藏  举报