[bzoj 5042]LWD的分科島

要求用優秀的複雜度求靜態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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章