• [CF875D] High Cry


    Description

    给定一个长度为 (n (n le 2 imes 10^5)) 的数列 (a_i),求满足区间 (OR) 大于区间最大值的区间的个数。

    Solution

    注意到区间或永远不会小于区间最大值

    于是转化为求区间或等于区间最大值的区间个数

    枚举最大值元素 (a_p),结合预处理得到其控制的(下标)区间 ([l,r])

    此时我们需要得到它向左/向右能扩展的最大长度

    考虑到单调性,利用 ST 表即可

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    const int N = 1000005;
    const int lgN = 20;
    const int dbg = 0;
    
    int n,a[N],lb[N],rb[N],lg2[N];
    
    struct St_table
    {
        int st[N][lgN];
    
        void build(int n,int *a)
        {
            for(int i=1;i<=n;i++)
            {
                st[i][0]=a[i];
            }
            for(int j=1;j<lgN;j++)
            {
                for(int i=1;i<=n;i++)
                {
                    st[i][j]=st[i][j-1]|st[i+(1<<(j-1))][j-1];
                }
            }
        }
    
        int query(int l,int r)
        {
            int p=lg2[r-l+1];
            int i=l, j=r;
            return st[i][p] | st[j-(1<<p)+1][p];
        }
    } st;
    
    void build_right_bound()
    {
        stack <int> s;
        memset(rb,0,sizeof rb);
        for(int i=1;i<=n;i++)
        {
            while(s.size() && a[s.top()]<=a[i])
            {
                rb[s.top()]=i-1;
                s.pop();
            }
            s.push(i);
        }
        for(int i=1;i<=n;i++)
        {
            if(rb[i]==0)
            {
                rb[i]=n;
            }
        }
    }
    
    void build_left_bound()
    {
        stack <int> s;
        memset(lb,0,sizeof lb);
        for(int i=n;i>=1;--i)
        {
            while(s.size() && a[s.top()]<a[i])
            {
                lb[s.top()]=i+1;
                s.pop();
            }
            s.push(i);
        }
        for(int i=1;i<=n;i++)
        {
            if(lb[i]==0)
            {
                lb[i]=1;
            }
        }
    }
    
    int get_left(int p,int len)
    {
        int l=p-len+1, r=p;
        l=max(l,1ll);
        return st.query(l,r);
    }
    
    int get_right(int p,int len)
    {
        int l=p, r=p+len-1;
        r=min(r,n);
        return st.query(l,r);
    }
    
    int bisect_left(int p,int mask)
    {
        int l=1, r=p+1;
        while(l<r)
        {
            int mid=(l+r)/2;
            if(get_left(p,mid) & ~mask) r=mid;
            else l=mid+1;
        }
        return l-1;
    }
    
    int bisect_right(int p,int mask)
    {
        int l=1, r=n-p+2;
        while(l<r)
        {
            int mid=(l+r)/2;
            if(get_right(p,mid) & ~mask) r=mid;
            else l=mid+1;
        }
        return l-1;
    }
    
    void self_check1()
    {
        cout<<"monostack dataout:"<<endl;
        for(int i=1;i<=n;i++)
        {
            cout<<i<<" "<<lb[i]<<","<<rb[i]<<endl;
        }
    }
    
    void self_check2()
    {
        cout<<"st_table selfcheck:"<<endl;
        for(int i=1;i<=n;i++)
        {
            for(int j=i;j<=n;j++)
            {
                int ans=st.query(i,j);
                int chk=0;
                for(int k=i;k<=j;k++)
                {
                    chk|=a[k];
                }
                cout<<(ans==chk);
            }
        }
        cout<<endl;
    }
    
    signed main()
    {
        ios::sync_with_stdio(false);
    
        cin>>n;
        for(int i=1;i<=n;i++) cin>>a[i];
    
        for(int i=1;i<=n;i++) lg2[i]=log2(i);
    
        build_right_bound();
        build_left_bound();
    
        if(dbg) self_check1();
    
        st.build(n,a);
    
        if(dbg) self_check2();
    
        int ans=0;
    
        for(int i=1;i<=n;i++)
        {
            int ql=lb[i], qr=rb[i];
            int al=bisect_left(i,a[i]);
            int ar=bisect_right(i,a[i]);
    
            al=min(al,i-lb[i]+1);
            ar=min(ar,rb[i]-i+1);
    
            if(dbg) cout<<"i="<<i<<"  "<<al<<" "<<ar<<" "<<endl;
    
            ans+=al*ar;
        }
    
        if(dbg) cout<<"src_ans = "<<ans<<endl;
    
        ans=n*(n+1)/2-ans;
    
        cout<<ans<<endl;
    }
    
    
  • 相关阅读:
    由当前acitivty直接退到桌面
    Android中SharedPreference多进程数据共享出错
    java回调机制
    Android 监听apk安装替换卸载广播
    jquery中如何退出each循环
    旋转六面体源码
    用CSS3制作的旋转六面体动画
    CSS中常用的字体单位:px、em、rem和%的区别
    css属性简写集合
    小游戏--别踩白块
  • 原文地址:https://www.cnblogs.com/mollnn/p/13575823.html
Copyright © 2020-2023  润新知