您的位置:首页 > 其它

bzoj 3166: [Heoi2013]Alo 可持久化trie

2013-10-31 19:27 561 查看
题意 : 选取一个区间 区间中的第二大的那个数 可以跟 区间中的任意一个数 进行 异或得到一个区间内的最大的值。

问任意选取区间,问最大的那个 异或的值是多少。 ?

枚举每个数是 区间中的 第二大的值, 找到 可行的区间,可行区间就是 : [ 左边第二个比这个大的数的下标 +1,右边第二个比这个数大的数的下标-1];

然后 可持久化 trie ,求 区间 对于 a 的最大的异或值。

怎么求 这个区间 ?

维护下标即可。 排序后 ,从 右往左添加 下标的值, 这样就保证了 ,已经添加进去的值一定比当前的值大, 这样,我们只要求比当前这个点的原来的下标的 值的 upper_bound 的 upper_bound 的值就是 右边第二大的值下标。

同理 左边的也可求。

/**************************************************************
Problem: 3166
User: OceanLight
Language: C++
Result: Accepted
Time:892 ms
Memory:229988 kb
****************************************************************/

#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <cstring>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <assert.h>
#include <queue>
#define REP(i,n) for(int i=0;i<n;i++)
#define TR(i,x) for(typeof(x.begin()) i=x.begin();i!=x.end();i++)
#define ALLL(x) x.begin(),x.end()
#define SORT(x) sort(ALLL(x))
#define CLEAR(x) memset(x,0,sizeof(x))
#define FILLL(x,c) memset(x,c,sizeof(x))
using namespace std;
const double eps = 1e-9;
#define LL long long
#define pb push_back
const int maxn  = 310000;
int num[maxn];
struct Node{
Node *s[2];
int sum;
}nodes[maxn*60];
Node *root[maxn],*null;
int C;
int n;
void init(){
C=0;
root[0] = null = &nodes[C++];
null->s[0] = null->s[1] = null;
null->sum = 0;
}
Node *insert(int v,int d,Node *root){
Node *rt = &nodes[C++];
rt->s[0] = root->s[0];
rt->s[1] = root->s[1];
rt->sum = root->sum+1;
if(d<0)return rt;
int p = (v>>d)&1;
rt->s[p] = insert(v,d-1,root->s[p]);
return rt;
}
int query(int v,int d,Node *rt1,Node *rt2){
if(d<0)return 0;
int p = (v>>d)&1;
if(rt2->s[p^1]->sum - rt1->s[p^1]->sum){
//  cout << d << " dd " << (1<<d)<< endl;
return (1<<d)+query(v,d-1,rt1->s[p^1],rt2->s[p^1]);
}
return query(v,d-1,rt1->s[p],rt2->s[p]);
}
const int K = 31;
int l[maxn],r[maxn],l2[maxn],r2[maxn];
void solve(){
init();
for(int i =1;i<=n;i++){
//  cout << num[i]<< endl;
root[i] =  insert(num[i],K,root[i-1]);
}
int ans = 0 ;
for(int i=1;i<=n;i++){
if(r2[i] == n && l2[i] == 0) continue;
int ret = query(num[i],K,root[l[i]],root[r[i]-1]);
// cout << ret << " "<< i << " "<< l[i] << " " << r[i]-1<<endl;
ans = max(ret,ans);
}
cout << ans <<endl;

}
struct S{
int num;
int id;
bool operator<(const S &b)const {
return num< b.num;
}
}s[maxn];
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&s[i].num);
num[i] = s[i].num;
s[i].id = i;
}
sort(s+1,s+n+1);
multiset<int>st;
multiset<int>::iterator it,it2;
st.insert(n+1);
st.insert(n+1);
st.insert(0);
st.insert(0);
for(int i=n;i>0;i--){
st.insert(s[i].id);
//cout << s[i].id<<endl;
it2 = it = st.lower_bound(s[i].id);
// cout << "  ** "<< *it<<endl;
it++;
r2[s[i].id] = *it;
it++;
it2--;
l2[s[i].id] = *it2;
it2--;
r[s[i].id] = *it;
l[s[i].id] = *it2;
//cout << s[i].id << " "  << *it<< "   "<<*it2<<endl;
}
solve();
return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: