回家了效率就是高啊。。。。
#include<bits/stdc++.h>
#define MAXN 700005 * 44
typedef long long ll;
using namespace std;
ll n,m,rt[MAXN],ch[MAXN][2],cnt[MAXN],num[MAXN],tot,yl[MAXN],ans = 0;
struct node{
ll l,r,maxl,sum,bj;
friend bool operator < (node x , node y){
return x.sum < y.sum;
}
};
priority_queue<node>q;
void add(ll &a , ll b , ll z , ll dep , ll nowx){
a = ++tot , cnt[a] = cnt[b] + 1;
ll t = ((z >> dep) & 1);
ch[a][t ^ 1] = ch[b][t ^ 1];
if(dep == (-1)){yl[a] = nowx ; return; }
add(ch[a][t] , ch[b][t] , z , dep - 1 , nowx);
return;
}
ll que(ll a , ll b , ll z , ll dep){//查詢區間a----b中 那一位異或z最大
ll t = ((z >> dep) & 1);
if(dep == (-1))return yl[b];
if(cnt[ch[b][t ^ 1]] - cnt[ch[a][t ^ 1]])return que(ch[a][t ^ 1] , ch[b][t ^ 1] , z , dep - 1);
else return que(ch[a][t] , ch[b][t] , z , dep - 1);
}
int main(){
cin>>n>>m;tot = 0;num[0] = 0;
add(rt[0] , 0ll , 0ll , 31 , 0ll);
for(ll i = 1 ; i <= n ; i++){
scanf("%lld" , &num[i]);
num[i] = num[i - 1] ^ num[i];
add(rt[i] , rt[i - 1] , num[i - 1] , 31 , i);
}
node uu,u1;
for(int i = 1 ; i <= n ; i++){
uu.l = 1;uu.bj = i;uu.r = i;
uu.maxl = que(rt[uu.l - 1] , rt[uu.r] , num[uu.bj] , 31);
uu.sum = num[uu.bj] ^ num[uu.maxl - 1];
q.push(uu);
}
while(m--){
uu = q.top();q.pop();ans += uu.sum;
u1.bj = uu.bj;
if(uu.l < uu.maxl){
u1.l = uu.l , u1.r = uu.maxl - 1;
u1.maxl = que(rt[u1.l - 1] , rt[u1.r] , num[u1.bj] , 31) , u1.sum = num[u1.bj] ^ num[u1.maxl - 1];
q.push(u1);
}
if(uu.maxl < uu.r){
u1.l = uu.maxl + 1 , u1.r = uu.r;
u1.maxl = que(rt[u1.l - 1] , rt[u1.r] , num[u1.bj] , 31) , u1.sum = num[u1.bj] ^ num[u1.maxl - 1];
q.push(u1);
}
}
cout<<ans<<endl;
}
就是跟超級鋼琴的想法差不多。。。。
但好像還有更優秀的做法。。。。
我這個做法 是左右的。。。。。比較假。。。。。
然後有個巨佬有個更加優秀的做法。。。但我不會