要求用優秀的複雜度求靜態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;
}