luoguP5283 [十二省聯考2019]異或糉子

回家了效率就是高啊。。。。

#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;
}

就是跟超級鋼琴的想法差不多。。。。
但好像還有更優秀的做法。。。。
我這個做法 是O(k2loga)O(k^2loga)左右的。。。。。比較假。。。。。

然後有個巨佬有個更加優秀的做法。。。但我不會

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章