• CF484E Sign on Fence (可持久化线段树+二分答案+区间合并)


    题意:

    给定一个长度为n的序列a[i]。给定m次询问。

    每次查询为l,r,w,表示在区间l,r中,问对于连续的长为w的一段中最小的数字的最大值是多少。

    题解:

    先把所有元素按高度从大到小排序,以高度为时间轴,元素编号为下标建立可持久化线段树。

    那么,第i棵线段树只会保存高度大于等于i的元素下标情况。

    对于每个询问,二分答案,在当前二分答案的线段树中找区间l r内最长的连续线段,这里涉及区间合并,是之前从来没有接触过的知识点。

    这道题无论是建树方法还是线段树信息的维护都是从没接触过的,需要好好复习。

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e5+100;
    const int M=maxn*40;
    int a[maxn],n,q,T[maxn];
    int tot=1;
    vector<pair<int,int> > z;
    struct node {
        int l,r;
        int len,maxLen,pre,suf;
        //len表示每个节点代表的区间长度
        //maxLen表示每个节点内部最长的连续区间的长度
        //pre表示每个节点代表的区间的最大前缀
        //suf表示每个节点代表的区间的最大后缀 
    }segTree[M];//可持久化线段树结构体 
    bool cmp (pair<int,int> x,pair<int,int> y) {
        return x.first>y.first;//先按高度从大到小排序 
    }
    void push_up (int i) {
        if (segTree[segTree[i].l].len==segTree[segTree[i].l].pre) {
            segTree[i].pre=segTree[segTree[i].l].len+segTree[segTree[i].r].pre;
        }
        else {
            segTree[i].pre=segTree[segTree[i].l].pre;
        }
        
        if (segTree[segTree[i].r].len==segTree[segTree[i].r].suf) {
            segTree[i].suf=segTree[segTree[i].r].len+segTree[segTree[i].l].suf;
        }
        else {
            segTree[i].suf=segTree[segTree[i].r].suf;
        }
        
        segTree[i].maxLen=max(segTree[i].pre,segTree[i].suf);
        segTree[i].maxLen=max(segTree[i].maxLen,segTree[segTree[i].l].suf+segTree[segTree[i].r].pre);
        segTree[i].maxLen=max(segTree[i].maxLen,max(segTree[segTree[i].l].maxLen,segTree[segTree[i].r].maxLen));
    } 
    
    void up (int &root,int lst,int l,int r,int p) {
        root=tot++;
        segTree[root]=segTree[lst];
        segTree[root].len=r-l+1;
        segTree[lst].len=r-l+1;
        if (l==r) {
            segTree[root].maxLen=1;
            segTree[root].pre=segTree[root].suf=1;
            return;
        }
        int mid=(l+r)>>1;
        if (p<=mid) 
            up(segTree[root].l,segTree[lst].l,l,mid,p);
        else
            up(segTree[root].r,segTree[lst].r,mid+1,r,p);
        push_up(root);
    }
    
    node merge (node x,node y) {
        node ans;
        if (x.len==0) return y;
        if (x.len==x.pre) {
            ans.pre=x.len+y.pre;
        }
        else {
            ans.pre=x.pre;
        }
        
        if (y.suf==y.len) {
            ans.suf=y.len+x.suf;
        }
        else {
            ans.suf=y.suf;
        }
        
        ans.len=x.len+y.len;
        ans.maxLen=max(ans.suf,ans.pre);
        ans.maxLen=max(ans.maxLen,x.suf+y.pre);
        ans.maxLen=max(ans.maxLen,max(x.maxLen,y.maxLen));
        return ans;
    }
    
    node query (int root,int l,int r,int L,int R) {
        if (l>=L&&r<=R) {
            return segTree[root];
        }
        node ans;
        ans.l=ans.len=ans.pre=ans.suf=ans.r=ans.maxLen=0;
        int mid=(l+r)>>1;
        if (L<=mid) ans=merge(ans,query(segTree[root].l,l,mid,L,R));
        if (R>mid) ans=merge(ans,query(segTree[root].r,mid+1,r,L,R));
        return ans;
    }
    
    int main () {
        scanf("%d",&n);
        for (int i=1;i<=n;i++) {
            scanf("%d",a+i);
            z.push_back(make_pair(a[i],i));
        }
        sort(z.begin(),z.end(),cmp);
        for (int i=0;i<n;i++) up(T[i+1],T[i],1,n,z[i].second);//以高度为轴,编号为下标建立线段树 
        scanf("%d",&q);
        while (q--) {
            int ql,qr,w;
            scanf("%d%d%d",&ql,&qr,&w);
            int l=1,r=n,ans=0;
            while (l<=r) {
                int mid=(l+r)>>1;
                if (query(T[mid],1,n,ql,qr).maxLen>=w) {
                    ans=mid;
                    r=mid-1;
                }
                else {
                    l=mid+1;
                }
            }
            //printf("%d
    ",ans);
            printf("%d
    ",z[ans-1].first);
        }
    }
     


  • 相关阅读:
    官方文档翻译-Today
    RAC & MVVM 学习资料整理
    35种常用字体
    中文字体的种类
    自言自语(三)--部分中文字体
    自言自语(二)--英文无衬线体和有衬线体
    sketch字体设置技巧(一)---通过锚点改变字体形态
    提高设计档次的8个方法
    知识汇总09~bootstrap-select在Vue中的封装
    知识汇总08~字符串截取
  • 原文地址:https://www.cnblogs.com/zhanglichen/p/13958340.html
Copyright © 2020-2023  润新知