• 【BZOJ-3956】Count ST表 + 单调栈


    3956: Count

    Time Limit: 10 Sec  Memory Limit: 512 MB
    Submit: 173  Solved: 99
    [Submit][Status][Discuss]

    Description

    Input

    Output

    Sample Input

    3 2 0
    2 1 2
    1 1
    1 3

    Sample Output

    0
    3

    HINT

    M,N<=3*10^5,Ai<=10^9

    Source

    CH Round#64 MFOI杯水题欢乐赛day1 By Gromah

    Solution

    思路有了之后,比较好写的一道题

    首先我们计算以每个点为区间左端的答案,以及区间右端的答案,利用单调栈可以$O(N)$的处理出来

    同样可以预处理出它们的前缀和

    然后我们考虑一次询问,假如我们得到$[l,r]$中的最大值位置mp

    那么我们的答案,相当于是询问区间$[l,mp]$中所有点作为左端的答案与$[mp+1,r]$中所有点作为右端点的答案

    那么显然前缀和计算就好,至于查询最大位置?线段树/ST表都可以处理

    这里采用ST表,总复杂度是$O(NlogN+M)$

    Code

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    inline int read()
    {
        int x=0,f=1; char ch=getchar();
        while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
        while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    #define MAXN 300010
    int N,M,T,h[MAXN]; long long last;
    inline int GetL (int x,int y) {if (T) return min((x+last-1)%N,(y+last-1)%N)+1; else return min(x,y);}
    inline int GetR (int x,int y) {if (T) return max((x+last-1)%N,(y+last-1)%N)+1; else return max(x,y);}
    int log2[MAXN],dp[MAXN][21];
    inline int MaxPos(int x,int y) {return h[x]>h[y]? x:y;}
    void ST()
    {
        log2[0]=-1;
        for (int i=1; i<=N; i++) 
            if (i&(i-1)) log2[i]=log2[i-1];
                else log2[i]=log2[i-1]+1;
        for (int i=1; i<=N; i++) dp[i][0]=i;
        for (int j=1; (1<<j)<=N; j++)
            for (int i=1; i+(1<<j)-1<=N; i++)
                dp[i][j]=MaxPos(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
    }
    inline int RMQ(int l,int r)
    {
        int tmp=log2[r-l+1];
        return MaxPos(dp[l][tmp],dp[r-(1<<tmp)+1][tmp]);
    }
    long long AnsL[MAXN],AnsR[MAXN];
    int stack[MAXN],top;
    void PreWork()
    {
        top=0;
        stack[++top]=h[1];
        for (int i=2; i<=N; i++)
            {
                while (top && h[i]>stack[top]) AnsL[i]++,top--;
                if (top) AnsL[i]++;
                while (top && h[i]>=stack[top]) top--;
                stack[++top]=h[i];
            }
        top=0;
        stack[++top]=h[N];
        for (int i=N-1; i>=1; i--)
            {
                while (top && h[i]>stack[top]) AnsR[i]++,top--;
                if (top) AnsR[i]++;
                while (top && h[i]>=stack[top]) top--;
                stack[++top]=h[i];
            }
        for (int i=1; i<=N; i++) AnsL[i]+=AnsL[i-1],AnsR[i]+=AnsR[i-1];
        ST();
    }
    inline void Solve(int L,int R)
    {
        int maxp=RMQ(L,R);
        printf("%lld
    ",last=AnsR[maxp-1]-AnsR[L-1]+AnsL[R]-AnsL[maxp]);
    }
    int main()
    {
        N=read(),M=read(),T=read();
        for (int i=1; i<=N; i++) h[i]=read();
        PreWork();
        while (M--)
            {
                int x=read(),y=read();
                int L=GetL(x,y),R=GetR(x,y);
                Solve(L,R);
            }
        return 0;
    }
  • 相关阅读:
    蓝牙基础学习
    树莓派识别TF卡内存错误导致内存可用减小解决方法
    有谁知道openwrt的系统的编译,烧录原理不吝赐教!
    树莓派显示屏输出设置
    树莓派连接摄像头做wifi视频
    Python3 安装PyUserInput从而实现鼠标点击事件
    树莓派ssh连接并使用sftp协议拷贝文件到电脑
    python tkinter 中 listbox绑定scrollbar实现自动循环滚动
    Python Tkinter学习
    代理模式
  • 原文地址:https://www.cnblogs.com/DaD3zZ-Beyonder/p/5754619.html
Copyright © 2020-2023  润新知