[BZOJ5042]LWD的分科岛
题目描述
大家都知道在文理分科的时候总是让人纠结的,纠结的当然不只是自己。
比如 YSY 就去读了文科, LWD 知道了很气。
于是他就去卡了 BZOJ 测评机, 晚上他做了一个谜一样的梦,自己在一座全是 YSY 的分科岛。这里有 YSY 草, YSY 花, YSY 糖……每个 YSY 都有一个美( Ti)丽( Zhong)值。
当然没有小于零的体重啦!LWD 于是不惜重金卖肉想买下这座岛,可是分科岛的岛主,是一位忠实的区间问题爱好者。
他想把小岛传给一个谜一样的爱好者,所以岛主给了 LWD 一个终极挑战——选出一片区域中最美丽的 YSY。
可是岛主的审美观不像 YYR那么专一,他有时喜欢现代美——最轻的,有时喜欢唐代美——最重的。
这让被欢喜冲昏了头脑(血液集中在下半身)的 LWD十分苦恼。
他要在规定时间内完成挑战赢得买岛的权利,于是只有求助 DalaoYYR,可是 YYR 要准备课件啊。
只有比 YYR 弱很多的你能够帮他了。挑战内容如下岛主将把 N 个 YSY 摆成一个条形,并给出所有 YSY 的美丽值。
挑出多少个就要看岛主心情了,他觉得 LWD 是条汉子就会给出很多很多的 YSY 满足他。岛主将给出 Q 个考验,
询问内容是在给定区间内求出最美丽的 YSY。你已经了解规则了,开始你的表演吧!
Input
第一行为一个整数 \(N\),表示岛主摆出了 \(N\) 个 YSY。
接下来一行$ N$ 个整数,表示每个 YSY 的美丽值(单位:kg),因为 YSY 整体很美所以 YSY
不会超过 \(10^9\)kg。
接下来一行一个整数 Q,表示岛主有 Q 个考验。\(Q<=1500000\)
接下来 Q 行,每行三个整数 opt, l, r 。
opt 等于 1 时表示岛主那时喜欢现代美,等于 2时代表岛主那时喜欢唐代美。
询问最美计划在区间[l, r]中进行
\(100\%\)的数据 \(N<= 3000000\), 美丽值不会超过 \(10^{9}\)
数据量巨大,请优化读入
Output
包括一个非负整数,表示有多少种放置的方案.
Sample Input
5 5
1 2 3 4 5
1 1 2
2 1 3
1 2 5
2 4 5
2 1 5
Sample Output
1
3
2
5
5
没错,笛卡尔树可以用来解\(RMG\)问题,我们对于每次查询区间进行离线。
首先,我们可以根据最大或最小建出大根堆或者是小根堆,
一个区间的最值就是其左右端点\(lca\)的值,利用离线\(lca\)我们可以做到时间复杂度为\(O(n*\alpha_n)\)的优秀复杂度。
此题严重卡常!!!!
代码如下:
#include <bits/stdc++.h>
using namespace std;
#define reg register
#define rep(a,b,c) for(reg int a=(b),a##_end_=(c); a<=a##_end_; ++a)
#define erep(i,x) for(int i=Head[x]; i; i=Nxt[i])
char U[20000],*p1=U,*p2=U;
inline int Read(void) {
register int res=0;
register char c;
while(c=(p1==p2&&(p2=(p1=U)+fread(U,1,20000,stdin),p1==p2)?EOF:*p1++),c<48||c>57);
do res=(res<<3)+(res<<1)+(c^48);
while(c=(p1==p2&&(p2=(p1=U)+fread(U,1,20000,stdin),p1==p2)?EOF:*p1++),c>=48&&c<=57);
return res;
}
const int N=3e6+5,M=1500005,mod=1e9+7;
int n,q,stk[N],A[N],Ans[M],Tot,Head[N],to[N],Nxt[N],cost[N],lc[N],rc[N],Fa[N],mark[N];
struct query {
int op,L,R;
} B[N];
inline void AddEdgepair(int a,int b,int c) {
to[++Tot]=b,cost[Tot]=c,Nxt[Tot]=Head[a],Head[a]=Tot;
to[++Tot]=a,cost[Tot]=c,Nxt[Tot]=Head[b],Head[b]=Tot;
}
int find(int x) {
return x==Fa[x]?Fa[x]:Fa[x]=find(Fa[x]);
}
void dfs(int x) {
mark[x]=1;
if(lc[x])dfs(lc[x]),Fa[lc[x]]=x;
if(rc[x])dfs(rc[x]),Fa[rc[x]]=x;
erep(i,x) {
int y=to[i],Id=cost[i];
if(mark[y])Ans[Id]=find(y);
}
}
char buff[20000000],*iter=buff,Stk[15];
void _main(void) {
n=Read(),q=Read();
rep(i,1,n)A[i]=Read();
int tot=0;
rep(i,1,q)B[i].op=Read(),B[i].L=Read(),B[i].R=Read();
int top=0,root=0;
stk[top=1]=root=1;
rep(i,2,n) {
int x=0;
while(top&&A[stk[top]]>=A[i])x=stk[top--];
!top?root=i,lc[i]=x:lc[i]=x,rc[stk[top]]=i;
stk[++top]=i;
}
while(top>1)rc[stk[top-1]]=stk[top],top--;
rep(i,1,q)if(B[i].op==1)AddEdgepair(B[i].L,B[i].R,i);
rep(i,1,n)Fa[i]=i;
dfs(root);
Tot=0;
rep(i,1,n)Fa[i]=i,lc[i]=rc[i]=mark[i]=Head[i]=0;
stk[top=1]=root=1;
rep(i,2,n) {
int x=0;
while(top&&A[stk[top]]<=A[i])x=stk[top--];
!top?root=i,lc[i]=x:lc[i]=x,rc[stk[top]]=i;
stk[++top]=i;
}
while(top>1)rc[stk[top-1]]=stk[top],top--;
rep(i,1,q)if(B[i].op==2)AddEdgepair(B[i].L,B[i].R,i);
dfs(root);
rep(i,1,q) {
int X=A[Ans[i]];
if(!X)*iter++='0';
else {
int O=0;
for(; X;)Stk[++O]=(X%10)^48,X/=10;
for(; O;)*iter++=Stk[O--];
}
*iter++='\n';
}
fwrite(buff,1,iter-buff,stdout);
}
signed main() {
_main();
return 0;
}