P17533 [JAG 2026 Summer Camp #1] Longest Symmetry
[JAG 2026 Summer Camp #1] Longest Symmetry
安利一下我的博客!
思路
考虑对于每个
对于一个询问
- 对于所有
l\le i\le mid 且c_i\le l ,我们希望求出X_i-X_l 的最大值,即i 的最大值。这是一个三维偏序,不过注意到可以将i\ge l 的条件删去,因为如果i<l ,那么X_i-X_l 一定小于0 ,不会影响答案。 - 对于所有
l\le i\le mid 且c_i\ge l ,我们希望求出X_i-X_{c_i} 的最大值。这同样是一个三维偏序,但是因为i\ge c_i ,所以我们可以将i\ge l 的限制删掉,变为二维偏序。
离线后进行二维偏序即可,注意“对称房屋区间”的中心可能是
代码
时间复杂度
#include<bits/stdc++.h>
using namespace std;
const int N=4e5+50;
int n,q,a[N];
long long ans[N];
vector<pair<int,int> > qu[N],quu[N];
int c[N],cc[N],b[N],cnt=0,ct[N],p[N];
void solve(int x){while(b[x-p[x]-1]==b[x+p[x]+1]) p[x]++;}
void manacher()
{
p[1]=0;
int mm=1;
for(int i=2;i<=cnt;i++)
{
if(mm+p[mm]-1>=i) p[i]=min(mm+p[mm]-1-i,p[mm*2-i]);
solve(i);
if(i+p[i]-1>=mm+p[mm]-1) mm=i;
}
for(int i=1;i<=cnt;i++)
if(ct[i]) cc[ct[i]]=ct[i]-p[i]/2,c[ct[i]]=ct[i]-p[i-1]/2,c[ct[i]+1]=ct[i]+1-p[i+1]/2;
}
struct tree
{
long long tree[N];
int lowbit(int x) {return x&(-x);}
void clear(){ memset(tree,128,sizeof(tree));}
void update(int x,long long y) {for(int i=x;i<=n;i+=lowbit(i)) tree[i]=max(tree[i],y);}
long long query(int x)
{
long long res=tree[0];
for(int i=x;i;i-=lowbit(i)) res=max(res,tree[i]);
return res;
}
}tr,trr;
int main()
{
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
b[++cnt]=-2,b[++cnt]=-1;
for(int i=1;i<n;i++) b[++cnt]=a[i+1]-a[i],ct[cnt]=i,b[++cnt]=-1;
b[++cnt]=-3,manacher();
cin>>q;
for(int i=1;i<=q;i++)
{
int l,r;
cin>>l>>r;
int ll=l,rr=r,res=0;
while(ll<=rr)
{
int mid=(ll+rr)>>1;
if(a[mid]-a[l]<=a[r]-a[mid]) res=mid,ll=mid+1;
else rr=mid-1;
}
qu[res].push_back({l,i});
if(res!=r) ans[i]=a[res+1]-a[res]+2*min(a[res]-a[cc[res]],min(a[res]-a[l],a[r]-a[res+1]));
if(res+1<=r) quu[res+1].push_back({r,i});
}
tr.clear(),trr.clear();
for(int i=1;i<=n;i++)
{
tr.update(c[i],a[i]*2),trr.update(n-c[i]+1,(a[i]-a[c[i]])*2);
if(i!=1) tr.update(cc[i-1],a[i-1]+a[i]),trr.update(n-cc[i-1]+1,(a[i-1]-a[cc[i-1]])*2+a[i]-a[i-1]);
for(int j=0;j<qu[i].size();j++) ans[qu[i][j].second]=max(ans[qu[i][j].second],max(trr.query(n-qu[i][j].first+1),tr.query(qu[i][j].first)-a[qu[i][j].first]*2));
}
tr.clear(),trr.clear();
for(int i=1;i<=n;i++) c[i]=i-c[i]+i,cc[i]=i+1+i-cc[i];
for(int i=n;i>=1;i--)
{
tr.update(n-c[i]+1,-a[i]*2),trr.update(c[i],(a[c[i]]-a[i])*2);
if(i!=n) tr.update(n-cc[i]+1,-(a[i+1]+a[i])),trr.update(cc[i],(a[cc[i]]-a[i+1])*2+a[i+1]-a[i]);
for(int j=0;j<quu[i].size();j++) ans[quu[i][j].second]=max(ans[quu[i][j].second],max(tr.query(n-quu[i][j].first+1)+a[quu[i][j].first]*2,trr.query(quu[i][j].first)));
}
for(int i=1;i<=q;i++) cout<<ans[i]<<"\n";
return 0;
}