社区讨论
O(nq)分治做法求卡常
P14638[NOIP2025] 序列询问参与者 4已保存回复 5
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 5 条
- 当前快照
- 1 份
- 快照标识符
- @min7jhcd
- 此快照首次捕获于
- 2025/12/01 21:51 3 个月前
- 此快照最后确认于
- 2025/12/03 21:40 3 个月前
rt,TLE on #19
CPP#include<iostream>
#define ll long long
#define ull unsigned long long
using namespace std;
const int N=5e4+5;
const ll INF=1e18;
int n,m;
int q[N],pos[N];
ll sum[N],ans[N],f[N],g[N][20],mx[N][20][20];
inline int read(){
int x=0,f=1;
char c=getchar();
while(c<48||c>57){
if(c=='-') f=-1;
c=getchar();
}
while(c>=48&&c<=57){
x=(x<<3)+(x<<1)+c-48;
c=getchar();
}
return f==-1?-x:x;
}
ll chkmax(ll &x,ll y){ return x=max(x,y);}
void solve(int l,int r,int L,int R){
if(r-l+1<L) return;
int mid=(l+r)>>1;
if(l<mid) solve(l,mid-1,L,R);
if(r>mid) solve(mid+1,r,L,R);
for(int i=max(l,mid-R+1);i<=min(r,mid+R-1);i++) f[i]=-INF;
int p=max(l,mid-R+1),h=1,t=0;
for(int i=max(mid,p+L-1);i<=min(r,p+R-1);i++){
while(h<=t&&sum[q[t]]<=sum[i]) t--;
q[++t]=i;
}
chkmax(f[p],sum[q[h]]-sum[p-1]);
for(int i=p+1;i<=mid;i++){
chkmax(f[i],f[i-1]);
if(i+R-1<=r){
while(h<=t&&sum[q[t]]<=sum[i+R-1]) t--;
q[++t]=i+R-1;
}
while(h<=t&&q[h]<i+L-1) h++;
if(h<=t) chkmax(f[i],sum[q[h]]-sum[i-1]);
}
p=min(mid+R-1,r),h=1,t=0;
for(int i=min(mid-1,p-L);i>=max(l-1,p-R);i--){
while(h<=t&&sum[q[t]]>=sum[i]) t--;
q[++t]=i;
}
chkmax(f[p],sum[p]-sum[q[h]]);
for(int i=p-1;i>=mid;i--){
chkmax(f[i],f[i+1]);
while(h<=t&&q[h]>i-L) h++;
if(i-R>=l-1){
while(h<=t&&sum[q[t]]>=sum[i-R]) t--;
q[++t]=i-R;
}
if(h<=t) chkmax(f[i],sum[i]-sum[q[h]]);
}
for(int i=max(l,mid-R+1);i<=min(r,mid+R-1);i++) chkmax(ans[i],f[i]);
}
signed main(){
n=read();
for(int i=1;i<=n;i++){
int x=read();
sum[i]=sum[i-1]+x;
}
int cnt=0;
for(int i=1,len=1;i<=n;i+=len,len<<=1){
for(int j=i;j<=min(i+len-1,n);j++) pos[j]=cnt;
for(int j=1;j<=n;j++) ans[j]=-INF;
solve(1,n,i,min(i+len-1,n));
for(int j=1;j<=n;j++) g[j][cnt]=ans[j];
cnt++;
}
for(int i=1;i<=n;i++){
for(int j=0;j<cnt;j++){
for(int k=0;k<cnt;k++) mx[i][j][k]=-INF;
}
}
for(int i=1;i<=n;i++){
for(int j=0;j<cnt;j++){
mx[i][j][j]=g[i][j];
for(int k=j+1;k<cnt;k++) mx[i][j][k]=max(mx[i][j][k-1],g[i][k]);
}
}
m=read();
while(m--){
int l=read(),r=read();
ull res=0;
int p=pos[l],q=pos[r];
if(p==q){
for(int i=1;i<=n;i++) ans[i]=-INF;
solve(1,n,l,r);
for(int i=1;i<=n;i++) res^=1ull*i*ans[i]/*,cout<<ans[i]<<' '*/;
cout/*<<endl*/<<res<<endl;
continue;
}
for(int i=1;i<=n;i++) ans[i]=mx[i][p+1][q-1];
solve(1,n,l,(1<<p+1)-1);
solve(1,n,1<<q,r);
for(int i=1;i<=n;i++) res^=1ull*i*ans[i]/*,cout<<ans[i]<<' '*/;
cout/*<<endl*/<<res<<endl;
}
return 0;
}
回复
共 5 条回复,欢迎继续交流。
正在加载回复...