AtCoder Regular Contest 100 (ARC100) E - Or Plus Max 其他

原文链接https://www.cnblogs.com/zhouzhendong/p/9251448.html

题目传送门 - ARC100E

题意

  给定一个正整数 $n(n\leq 18)$。

  然后给定一行共 $2^n$ 个正整数 $a_0,a_1,\cdots,a_{2^n-1}$ 。

  对于每一个 $k(1\leq k<2^n)$ ,输出满足 $i\ OR\ j \leq k$ 的最大 $a_i+a_j$ 值。

题解

  看到这题的心情:为啥不早做这题!!这题过的人怎么这么少??

  连我都只想了几分钟,那么那些大佬是不是都一眼秒?

  好了讲题:

  考虑对于每一个 $k$ 处理出满足 $k\ OR\ x=k$ 的所有 $x$ 中 $a_x$ 最大的两个。其中 $k=0$ 的时候特殊一点注意一下。

  具体怎么求???

  考虑一个 $k$ 要处理的东西,可以从两个方面继承:一个是自己本身的数 $a_k$ ,另一部分是把 $k$ 的任意一个非零位换成 $0$ 得到的 $k^{\prime}$ 的结果。

  然后回到原题,弄个前缀 $\max$ 就好了。

代码

#include <bits/stdc++.h>
using namespace std;
const int N=1<<19;
int n,s,a[N];
int id[N][2];
bool cmp(int A,int B){
	return a[A]<a[B];
}
int main(){
	scanf("%d",&n);
	s=1<<n;
	for (int i=0;i<s;i++)
		scanf("%d",&a[i]);
	a[s]=-1;
	id[0][0]=0,id[0][1]=s;
	for (int i=1;i<s;i++){
		id[i][0]=i,id[i][1]=s;
		int x[4];
		for (int j=0;j<n;j++)
			if (i&(1<<j)){
				int _i=i^(1<<j);
				x[0]=id[i][0],x[1]=id[i][1];
				x[2]=id[_i][0],x[3]=id[_i][1];
				sort(x,x+4,cmp);
				id[i][0]=x[3],id[i][1]=x[2]==x[3]?x[1]:x[2];
			}
	}
	int mx=0;
	for (int i=1;i<s;i++){
		mx=max(mx,a[id[i][0]]+a[id[i][1]]);
		printf("%d\n",mx);
	}
	return 0;
}

  

posted @ 2018-07-01 21:31  zzd233  阅读(585)  评论(0编辑  收藏  举报