zoukankan      html  css  js  c++  java
  • [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("
    ");
        return 0;
    }
  • 相关阅读:
    3.3 直方图处理与函数绘图
    光头强
    考试代码模板
    【2015初赛】预备
    NOIP2018 模拟题
    NOIP2017 模拟赛
    【解题报告】树形DP入门
    【解题报告】区间DP
    【解题报告】树形背包
    二分刷题单
  • 原文地址:https://www.cnblogs.com/wang9897/p/10481022.html
Copyright © 2011-2022 走看看