CodeForces

https://codeforces.com/problemset/problem/1417/E

正解:

从二进制最高位开始算,不断分开分开就是答案了。

每一位存下来按照01分开,贪心做事情,具体看代码吧,挺简单

#include<iostream>
#include<vector>
using namespace std;
typedef long long ll;
const int maxn = 3e5+11;
vector<int>chal;

ll dp[100][10];
int list[maxn];

ll ans = 0;

int dfs(vector<int>ins ,int dep){
	if(dep < 0 ) return 0;
	if(ins.size() == 0) return 0;
	vector<int>cns;
	
	int cnt1=0,cnt0=0;
	for(int i=ins.size()-1;i>=0;i--){
		int x = (ins[i] >> dep)&1;
		if(x == 1){
			cnt1++;
			dp[dep][1] += cnt0;
		}
		else{
			cnt0++;
			dp[dep][0] += cnt1;
		}
	}
	
	for(int i = 0;i<ins.size();i++){
		int x = (ins[i] >> dep)&1;
		if(x == 0){
			cns.push_back(ins[i]);
		}
	}
	dfs(cns,dep-1);
	
	cns.clear();
	for(int i = 0;i<ins.size();i++){
		int x = (ins[i] >> dep)&1;
		if(x == 1){
			cns.push_back(ins[i]);
		}
	}
	dfs(cns,dep-1);
	cns.clear();
}


int main(){
	int n;
	scanf("%d",&n);
	
	for(int i=0;i<n;i++){
		int x;
		scanf("%d",&x);
		chal.push_back(x);
	}
	
	dfs(chal,30);
	ll cns = 0;
	ll ans =0 ;
	for(int i=30;i>=0;i--){
		if(dp[i][0] < dp[i][1]){
			cns += (1<<i);
		}
		ans += min(dp[i][0],dp[i][1]);
	}
	printf("%lld %lld",ans,cns);
	return 0;
}

  

还有一种做法是我第一次写的时候盲猜的,利用线段树动态开点暴力算异或对是不是变多了,。。。结果给T了,如果n是1e5说不定可以呢。。。

#include<iostream>
#include<cstring>
using namespace std;
const int maxn = 3e5+1111;
typedef long long ll;

struct Node{
	int l,r,ans;
}tree[maxn*40];


int list[maxn];
int cnt = 2;
int update(int & node,int be,int en,int i,int val){
	if(node == 0) node = ++cnt;
	int mid = be + en >> 1;
	if(be == en ){
		tree[node].ans += val;
		return 0;
	}
	if(i <= mid) update(tree[node].l,be,mid,i,val);
	else update(tree[node].r,mid+1,en,i,val);
	int l = tree[node].l;
	int r = tree[node].r;
	tree[node].ans = tree[l].ans + tree[r].ans;
}
int ask(int node,int be,int en,int LL,int RR){
	if(node == 0) return 0;
	int mid = be + en >> 1;
	if( LL <= be && en <= RR){
		return tree[node].ans;
	}
	int val1 = 0,val2 = 0;
	if(LL <= mid) val1 = ask(tree[node].l,be,mid,LL,RR);
	if(RR > mid) val2 = ask(tree[node].r,mid+1,en,LL,RR);
	return val1 + val2;
}
int init(){
	for(int i=0;i<=cnt;i++){
		tree[i].l = tree[i].r = tree[i].ans = 0;
	}
	cnt = 2;
	return 0;
}

int main(){
	int root = 1;
	int n;
	scanf("%d",&n);
	
	for(int i=0;i<n;i++){
		scanf("%d",&list[i]);
	}
	cnt = 2;
	ll ans = 1e17;
	
	int nn = 1e9+11;
	ll cns = 0;
	
	for(int i = 30;i>=0;i--){
		int x = 1<<i;
		ll a = 0;
		ll b = 0;
		for(int j=n-1;j>=0;j--){
			if(list[j] == 0){
				update(root,0,nn,0,1); 
				continue;
			}
			a += ask(root,0,nn,0,list[j]-1);
			update(root,0,nn,list[j],1);
		}
		for(int j=n-1;j>=0;j--){
			update(root,0,nn,list[j],-1);
		}
		
		for(int j=n-1;j>=0;j--){
			list[j] ^= x;
			if(list[j] == 0){
				update(root,0,nn,0,1); 
				continue;
			}
			b += ask(root,0,nn,0,list[j]-1);
			update(root,0,nn,list[j],1);
		}
		
		for(int j=n-1;j>=0;j--){
			update(root,0,nn,list[j],-1);
		}
		if(a <= b){
			for(int j=0;j<n;j++){
				list[j] ^= x;
			}
		}
		else{
			cns += x;
		}
		
		a = min(a,b);
		ans = min(a,ans);
	}
	

	printf("%lld %lld
",ans,cns);
	return 0;
} 



?

  

原文地址:https://www.cnblogs.com/lesning/p/13932445.html