zoukankan      html  css  js  c++  java
  • Educational Codeforces Round 61 (Rated for Div. 2) G(线段树,单调栈)

    #include<bits/stdc++.h>
    using namespace std;
    int st[1000007];
    int top;
    int s[1000007],t[1000007];
    int mx[4000007];
    int sum[4000007];
    int head[1000007],to[2000007],nex[2000007];
    int n,k;
    int a[10000077];
    int dfn;
    int tot;
    void pushup(int rt){
        mx[rt]=max(mx[rt<<1],mx[rt<<1|1]);
    }
    void pushdown(int rt){
        if(sum[rt]){
            sum[rt<<1]+=sum[rt];
            sum[rt<<1|1]+=sum[rt];
            mx[rt<<1]+=sum[rt];
            mx[rt<<1|1]+=sum[rt];
            sum[rt]=0;
        }
    }
    void change(int rt,int l,int r,int L,int R,int x){//线段树区间更新
        if(L<=l&&r<=R){
            sum[rt]+=x;
            mx[rt]+=x;
            return ;
        }
        pushdown(rt);
        int mid=(l+r)>>1;
        if(L<=mid)
            change(rt<<1,l,mid,L,R,x);
        if(R>mid)
            change(rt<<1|1,mid+1,r,L,R,x);
        pushup(rt);
    }
    void add(int x,int y){//链式前向星,连边
        nex[++tot]=head[x];//上一条边
        head[x]=tot;//最后一条边
        to[tot]=y;//连向的点
    }
    void dfs(int x){
        s[x]=++dfn;//这个点子树深度的最小值
        for(int i=head[x];i;i=nex[i])
            dfs(to[i]);
        t[x]=dfn;//这个点子树深度的最大值
    }
    int main(){
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            while(top&&a[st[top]]<a[i]){//单调栈
                add(i,st[top]);//连边,前一个是后一个离得最近的比它大的数的位置
                top--;
            }
            st[++top]=i;//进入栈顶
        }
        while(top){
            add(n+1,st[top]);//顶端的数字给一个根节点将它们建成树
            top--;
        }
        dfs(n+1);//从根节点遍历
        for(int i=1;i<=k;i++)
            change(1,1,n+1,s[i],t[i],1);
        printf("%d ",mx[1]);
        for(int i=k+1;i<=n;i++){
            change(1,1,n+1,s[i],t[i],1);//当区间右端点右移时,新加入区间的这个数会对原区间中比这个数小的数的答案+1,也就是将这个数在树上的子树中所有点的答案+1(这些答案+1的所有点中虽然包括区间之前的数但显然这些数的答案不会比区间内数的答案更大,最多只会与最大值相同)
            change(1,1,n+1,s[i-k],t[i-k],-1);//同样当区间左端点右移时,就将这个数在树上的子树中所有点的答案−1来确保区间之前的数的答案不会比区间中数的答案更优
            printf("%d ",mx[1]);
        }
    }

    保持热爱 不懈努力 不试试看怎么知道会失败呢(划掉) 世上无难事 只要肯放弃(划掉)
  • 相关阅读:
    查询对象模式(下)
    淘宝code
    C#中使用消息队列RabbitMQ
    MVC5模板部署到mono
    ventBroker简单实现
    http协议知识整理(转)
    创业者应该有的5个正常心态(转)
    观点:独立游戏开发者创业路上的11个‘坑’(转)
    应用程序框架实战三十四:数据传输对象(DTO)介绍及各类型实体比较(转)
    【技巧篇】解决悬浮的<header>、<footer>遮挡内容的处理技巧(转)
  • 原文地址:https://www.cnblogs.com/ldudxy/p/10611902.html
Copyright © 2011-2022 走看看