[bzoj 5042]LWD的分科岛

124 篇文章 2 订阅
6 篇文章 0 订阅

要求用优秀的复杂度求静态RMQ

这道题首先肯定不能带log,那可以考虑离线做,让询问右端点递增。
枚举右端点,用并查集fa[i]表示i~r的极值所在的位置,然后发现每次需要改变的位置可以用单调栈来计算,那复杂度就近似O(n)了。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdlib>
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;
}
inline void write(int x)
{
    if(x<0)putchar('-'),x=-x;
    if(x>9)write(x/10);
    putchar(x%10+'0');
}
inline void pr1(int x){write(x),putchar(' ');}
inline void pr2(int x){write(x),puts("");}
struct bian
{
    int x,y,next;
}e[1500010];int len,last[3000010];
inline void ins(int x,int y)
{
    len++;
    e[len].x=x;e[len].y=y;
    e[len].next=last[x];last[x]=len;
}
struct node
{
    int id,p;
}q[1500010];
int a[3000010],fa[2][3000010],ans[1500010],top[2],sta[2][3000010];
inline int findfa(int x,int id)
{
    if(fa[id][x]!=x)fa[id][x]=findfa(fa[id][x],id);
    return fa[id][x];
}
int main()
{
    //freopen("a.in","r",stdin);
    //freopen("a.out","w",stdout);
    int n=read(),m=read();
    for(int i=1;i<=n;i++)a[i]=read();
    for(int i=1;i<=m;i++)
    {
        q[i].id=read()-1,q[i].p=read();
        ins(read(),i);
    }
    for(int i=1;i<=n;i++)
    {
        fa[0][i]=i,fa[1][i]=i;
        while(top[0] && a[i]<a[sta[0][top[0]]])fa[0][sta[0][top[0]]]=i,top[0]--;
        sta[0][++top[0]]=i;
        while(top[1] && a[i]>a[sta[1][top[1]]])fa[1][sta[1][top[1]]]=i,top[1]--;
        sta[1][++top[1]]=i;
        int x=i;
        for(int k=last[x];k;k=e[k].next)
        {
            int y=e[k].y;
            ans[y]=findfa(q[y].p,q[y].id);
        }
    }
    for(int i=1;i<=m;i++)pr2(a[ans[i]]);
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值