LuoguP3793 由乃救爷爷

Description

题目链接:P3793

给定一个 $n$ 个数的序列,有 $m$ 个询问,每次询问区间最大值。

$1\leq n,m\leq 2\times 10^7$,保证数据随机。

Solution

考虑分块。

如果朴素分块肯定是不能过的 $O(N\sqrt{N})$,但是这题并没有修改操作,所以考虑先预处理出第 $l$ 个块到第 $r$ 个块的最大值、第 $i$ 个块的前缀最大值、第 $i$ 个块的后缀最大值。

每次询问的时候如果 $l,r$ 在同一个块内可以直接暴力,出现此情况应该是 $\frac{1}{\sqrt{N}}$,而单次暴力复杂度为 $O(\sqrt{N})$,所以总期望复杂度是 $O(N)$。

如果不在同一块内直接利用预处理出的结果 $O(1)$ 即可。

所以总的时间复杂度是 $O(N)$。

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#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%10+'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;
}