标签:ch int 题解 ql qr HEOI2013 区间 P4098 比其大
考虑原序列中的每一个值作为构成最终答案的那个次大值,那么其所在的合法区间最大时,其对答案的贡献最大。
一个值作为最大值时有两个合法的最大区间,一个是左边第二个比其大的位置和右边第一个比其大的位置构成的区间,另一个是左边第一个比其大的位置和右边第二个比其大的位置构成的区间,这两个区间都是开区间。确定区间可以从小到大排序,用双向链表一个一个删除即可。
然后就将问题简化了,现在要解决给定一个值,求给定区间与其的异或最大值,可以对原序列建可持久化\(Trie\),查询时直接在\(Trie\)上贪心就行。
实现细节看代码吧。
\(code:\)
#include<bits/stdc++.h>
#define maxn 3000010
using namespace std;
template<typename T> inline void read(T &x)
{
x=0;char c=getchar();bool flag=false;
while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
if(flag)x=-x;
}
int n,tot,ans;
int a[maxn],p[maxn],pre[maxn],nxt[maxn];
int rt[maxn],t[maxn][2],cnt[maxn];
bool cmp(const int &x,const int &y)
{
return a[x]<a[y];
}
void insert(int x,int k,int &p)
{
cnt[++tot]=cnt[p],t[tot][0]=t[p][0],t[tot][1]=t[p][1];
p=tot,cnt[p]++;
if(k==-1) return;
insert(x,k-1,t[p][(x>>k)&1]);
}
int query(int ql,int qr,int k,int x)
{
if(k==-1) return 0;
int ch=((x>>k)&1)^1;
if(cnt[t[qr][ch]]-cnt[t[ql][ch]])
return query(t[ql][ch],t[qr][ch],k-1,x)|(1<<k);
else return query(t[ql][ch^1],t[qr][ch^1],k-1,x);
}
int main()
{
read(n);
for(int i=1;i<=n;++i) pre[i]=i-1,nxt[i]=i+1,p[i]=i;
for(int i=1;i<=n;++i)
read(a[i]),rt[i]=rt[i-1],insert(a[i],30,rt[i]);
sort(p+1,p+n+1,cmp);
for(int i=1;i<=n;++i)
{
int l=pre[p[i]],r=nxt[p[i]];
nxt[l]=r,pre[r]=l;
if(l) ans=max(ans,query(rt[pre[l]],rt[r-1],30,a[p[i]]));
if(r!=n+1) ans=max(ans,query(rt[l],rt[nxt[r]-1],30,a[p[i]]));
}
printf("%d\n",ans);
return 0;
}
标签:ch,int,题解,ql,qr,HEOI2013,区间,P4098,比其大 来源: https://www.cnblogs.com/lhm-/p/12819058.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。