LuoguP3793 由乃救爷爷
Description
题目链接:P3793
给定一个 n 个数的序列,有 m 个询问,每次询问区间最大值。
1leq n,mleq 2times 10^7,保证数据随机。
Solution
考虑分块。
如果朴素分块肯定是不能过的 O(Nsqrt{N}),但是这题并没有修改操作,所以考虑先预处理出第 l 个块到第 r 个块的最大值、第 i 个块的前缀最大值、第 i 个块的后缀最大值。
每次询问的时候如果 l,r 在同一个块内可以直接暴力,出现此情况应该是 frac{1}{sqrt{N}},而单次暴力复杂度为 O(sqrt{N}),所以总期望复杂度是 O(N)。
如果不在同一块内直接利用预处理出的结果 O(1) 即可。
所以总的时间复杂度是 O(N)。
Code
代码语言:javascript复制#include<bits/stdc .h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define W while
#define I inline
#define RI register int
#define LL long long
#define Cn const
#define CI Cn int&
#define gc getchar
#define D isdigit(c=gc())
#define pc(c) putchar((c))
#define min(x,y) ((x)<(y)?(x):(y))
#define max(x,y) ((x)>(y)?(x):(y))
using namespace std;
namespace Debug{
Tp I void _debug(Cn char* f,Ty t){cerr<<f<<'='<<t<<endl;}
Ts I void _debug(Cn char* f,Ty x,Ar... y){W(*f!=',') cerr<<*f ;cerr<<'='<<x<<",";_debug(f 1,y...);}
Tp ostream& operator<<(ostream& os,Cn vector<Ty>& V){os<<"[";for(Cn auto& vv:V) os<<vv<<",";os<<"]";return os;}
#define gdb(...) _debug(#__VA_ARGS__,__VA_ARGS__)
}using namespace Debug;
namespace FastIO{
Tp I void read(Ty& x){char c;int f=1;x=0;W(!D) f=c^'-'?1:-1;W(x=(x<<3) (x<<1) (c&15),D);x*=f;}
Ts I void read(Ty& x,Ar&... y){read(x),read(y...);}
Tp I void write(Ty x){x<0&&(pc('-'),x=-x,0),x<10?(pc(x '0'),0):(write(x/10),pc(x '0'),0);}
Tp I void writeln(Cn Ty& x){write(x),pc('n');}
}using namespace FastIO;
Cn int N=2e7,S=10000,M=N/S;
namespace GenHelper{
unsigned z1,z2,z3,z4,b;
unsigned rand_(){b=((z1<<6)^z1)>>13;z1=((z1&4294967294U)<<18)^b;b=((z2<<2)^z2)>>27;z2=((z2&4294967288U)<<2)^b;b=((z3<<13)^z3)>>21;z3=((z3&4294967280U)<<7)^b;b=((z4<<3)^z4)>>12;z4=((z4&4294967168U)<<13)^b;return (z1^z2^z3^z4);}
}void srand(unsigned x){using namespace GenHelper;z1=x;z2=(~x)^0x233333333U;z3=x^0x1234598766U;z4=(~x) 51;}
int fread(){using namespace GenHelper;int a=rand_()&32767;int b=rand_()&32767;return a*32768 b;}
int n,m,seed,a[N 5],F[M 5][M 5],G[M 5],L[M 5][S 5],R[M 5][S 5];
unsigned long long Ans;
I int Q(CI l,CI r){
RI X=0;if(l/S==r/S){RI i;for(i=l;i<=r;i ) X=max(X,a[i]);return X;}//直接暴力
if(l/S 2<=r/S) X=F[l/S 2][r/S];X=max(X,max(R[l/S 1][l%S],L[r/S 1][r%S]));return X;
}
int main(){
RI i,j,l,r;read(n,m,seed),srand(seed);for(i=0;i<n;i ) a[i]=fread(),G[i/S 1]=max(G[i/S 1],a[i]);
for(i=1;i<=(n-1)/S 1;i ) for(j=i;j<=(n-1)/S 1;j ) F[i][j]=max(F[i][j-1],G[j]);//块间最值
for(i=0;i<n;i ) !(i%S)?L[i/S 1][i%S]=a[i]:L[i/S 1][i%S]=max(L[i/S 1][i%S-1],a[i]);
for(i=n-1;~i;i--) R[i/S 1][i%S]=max(R[i/S 1][i%S 1],a[i]);//前缀&后缀最大值
W(m--) l=fread()%n,r=fread()%n,l>r&&(swap(l,r),0),Ans =Q(l,r);
return writeln(Ans),0;
}