P14638 [NOIP2025] 序列询问 / query
弱化版。
草是谁做过弱化版考场上没想起来。有 85 pts 啊 /ll。
不过这个是不是确实没啥启发性啊 /yun。
分块,影响块 \([l,r]\) 中位置的答案的区间有四类。
-
\(l'\le l,r'\in[l,r]\)
-
\(l'\in[l,r],r\le r'\)
-
\(l'<l,r'<r\)
-
\(l\le l'\le r'\le r\)
假设区间长度为 \([L,R]\),以 \(L\) 为块长就能去掉第四种情况。
前两种枚举块内位置作为左/右端点,则另一端点的位置为一段区间,和弱化版中分治的处理类似,用 st 表维护前缀和 \(\min,\max\) 即可。这部分每块是 \(O(L)\) 的。
而第三种枚举右端点,左端点也为一段区间,右端点个数为 \(O(R-L)\)。
假设区间长度为 \([L,R]\)。前两种复杂度为 \(O(n)\),第三种为 \(O(\frac{n}{L}R)\)。
假设 \(\frac{R}{L}\) 为小常数时可以看作单次 \(O(n)\) 求解。
考虑对区间长度一维套一个倍增优化,预处理 \([2^i,2^{i+1})\) 的答案,最后合并整块两边散块可以 \(O(n)\) 求解。卡卡卡卡卡卡卡卡卡卡卡常就过了。
#include<bits/stdc++.h>
using namespace std;
#define cfast ios::sync_with_stdio(false);cin.tie(0),cout.tie(0)
#define ll long long
#define ull unsigned long long
inline void max_(ll &x,ll y){if(y>x)x=y;}
inline void min_(ll &x,ll y){if(y<x)x=y;}
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
const int N=5e4+5,M=16;
const ll inf=-1e12;
int n,a[N],lg[N];ll s[N],mx[N][M],mn[N][M],ans[N],w[N],res[N][M][M],f[N];
inline ll gtmx(int l,int r){int p=lg[r-l+1];return max(mx[l][p],mx[r-(1<<p)+1][p]);}
inline ll gtmn(int l,int r){int p=lg[r-l+1];return min(mn[l][p],mn[r-(1<<p)+1][p]);}
inline void solve(int L,int R){
for(int l=1,r=L;l<=n;l+=L,r=min(l+L-1,n)){
for(int j=l;j<=r;j++)
w[j]=(j-L>=0?s[j]-gtmn(max(j-R,0),j-L):inf);
for(int j=r-1;j>=l;j--)max_(w[j],w[j+1]);
for(int j=l;j<=r;j++)ans[j]=w[j];
for(int j=l;j<=r;j++)
w[j]=(j+L-1<=n?gtmx(j+L-1,min(j+R-1,n))-s[j-1]:inf);
for(int j=l+1;j<=r;j++)max_(w[j],w[j-1]);
for(int j=l;j<=r;j++)max_(ans[j],w[j]);
ll x=inf;
for(int j=r+1;j<=n;j++){
if(j-R+1>=l)break;
max_(x,s[j]-gtmn(max(j-R,0),l-1));
}
for(int j=l;j<=r;j++)max_(ans[j],x);
}
}
inline void UesugiErii(){
cin>>n;
for(int i=2;i<=n;i++)lg[i]=lg[i>>1]+1;
for(int i=1;i<=n;i++)
cin>>a[i],s[i]=s[i-1]+a[i],mx[i][0]=mn[i][0]=s[i];
for(int i=1;i<=lg[n];i++)
for(int j=0;j+(1<<i)-1<=n;j++){
mx[j][i]=max(mx[j][i-1],mx[j+(1<<i-1)][i-1]),
mn[j][i]=min(mn[j][i-1],mn[j+(1<<i-1)][i-1]);
}
for(int i=0;i<lg[n];i++){
solve(1<<i,(1<<i+1)-1);
for(int j=0;j<=n;j++)res[j][i][i]=ans[j];
}
for(int i=1;i<=n;i++)
for(int j=1;j<lg[n];j++)
for(int k=j+1;k<lg[n];k++)
res[i][j][k]=max(res[i][k][k],res[i][j][k-1]);
int q;cin>>q;
while(q--){
int L,R;ull t=0;cin>>L>>R;int l=lg[L],r=lg[R];
if(R<(L<<1)){
solve(L,R);
for(int i=1;i<=n;i++)t^=(ull)(i*ans[i]);
cout<<t<<'\n';
continue;
}
if(l+1<=r-1)
for(int i=1;i<=n;i++)f[i]=res[i][l+1][r-1];
else for(int i=1;i<=n;i++)f[i]=inf;
if(L!=(1<<l)){
solve(L,(1<<l+1)-1);
for(int i=1;i<=n;i++)max_(f[i],ans[i]);
}else for(int i=1;i<=n;i++)max_(f[i],res[i][l][l]);
if(R!=(1<<r+1)-1){
solve(1<<r,R);
for(int i=1;i<=n;i++)max_(f[i],ans[i]);
}else for(int i=1;i<=n;i++)max_(f[i],res[i][r][r]);
for(int i=1;i<=n;i++)t^=(ull)(i*f[i]);
cout<<t<<'\n';
}
}
signed main(){
//IO();
cfast;
int _=1;//cin>>_;
for(;_;_--)UesugiErii();
return 0;
}

浙公网安备 33010602011771号