P3793-由乃救爷爷【分块,ST表】
生活随笔
收集整理的這篇文章主要介紹了
P3793-由乃救爷爷【分块,ST表】
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
正題
題目鏈接:https://www.luogu.com.cn/problem/P3793
題目大意
給出nnn個數字的一個序列mmm次詢問區間最大值
保證數據隨機
1≤n,m≤2×1071\leq n,m\leq 2\times 10^71≤n,m≤2×107
解題思路
使用STSTST表可以做到O(1)O(1)O(1)詢問,但是預處理的時空復雜度都是O(nlog?n)O(n\log n)O(nlogn),且自帶大常數導致過不了。
如何加快預處理的時間,(因為是lxl的題目所以)考慮使用分塊。每次詢問可以分為整塊的部分和不是整塊的零散部分。
去掉沒有跨塊的情況,那么零散的部分就是塊內前后綴最大值。然后整塊的部分用STSTST表就好了。
那么沒有跨塊的情況是不是還需要給每個塊維護一個STSTST表?這樣空間還是過不了,其實可以考慮將沒有跨塊的情況按順序每個塊每個塊離線處理,這樣就可以過了。
但是數據保證隨機,所以隨機到同一個塊內的概率是1T\frac{1}{T}T1?,也就是期望n\sqrt nn?次,暴力處理是O(n)O(\sqrt n)O(n?)的,所以直接暴力處理就可以了
時間復雜度O(nlog?n+m)O(n\log\sqrt n+m)O(nlogn?+m)。
code
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; const int N=2e7+10; 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 read() {using namespace GenHelper;int a=rand_()&32767;int b=rand_()&32767;return a*32768+b; } int n,m,a[N],lg[N],p[N],q[N],g[5000][13]; int L[5000],R[5000],pos[N]; unsigned s; unsigned long long ans; int AskT(int l,int r){if(l>r)return 0;int z=lg[r-l+1];return max(g[l][z],g[r-(1<<z)+1][z]); } int main() {scanf("%d%d%u",&n,&m,&s);srand(s);for(int i=1;i<=n;i++)a[i]=read();int T=sqrt(n);for(int i=1;i<=T;i++)L[i]=R[i-1]+1,R[i]=i*T;if(R[T]!=n)++T,L[T]=R[T-1]+1,R[T]=n;for(int i=1;i<=T;i++){for(int j=L[i];j<=R[i];j++)pos[j]=i,g[i][0]=max(g[i][0],a[j]);p[L[i]]=a[L[i]];q[R[i]]=a[R[i]];for(int j=L[i]+1;j<=R[i];j++)p[j]=max(p[j-1],a[j]);for(int j=R[i]-1;j>=L[i];j--)q[j]=max(q[j+1],a[j]);}for(int j=1;(1<<j)<=T;j++)for(int i=1;i+(1<<j)-1<=T;i++)g[i][j]=max(g[i][j-1],g[i+(1<<j-1)][j-1]);for(int i=2;i<=T;i++)lg[i]=lg[i>>1]+1;for(int i=1;i<=m;i++){int l=read(),r=read();l=l%n+1;r=r%n+1;if(l>r)swap(l,r);int x=pos[l],y=pos[r];int tmp=0;if(x==y){for(int i=l;i<=r;i++)tmp=max(tmp,a[i]);}else{tmp=AskT(x+1,y-1);tmp=max(tmp,max(q[l],p[r]));}ans+=tmp;}printf("%llu\n",ans); }總結
以上是生活随笔為你收集整理的P3793-由乃救爷爷【分块,ST表】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: P5437-[XR-2]约定【拉格朗日差
- 下一篇: P1251-餐巾计划问题【费用流】