Justice(二进制位+DFS)-HDU - 6557

感受
有 点 简 单 , 一 开 始 还 担 心 精 度 问 题 , 后 来 想 了 想 与 精 度 无 关 有点简单,一开始还担心精度问题,后来想了想与精度无关
思路
考 虑 如 何 利 用 已 知 串 构 造 一 个 最 接 近 0.5 的 串 呢 ? 考虑如何利用已知串构造一个最接近0.5的串呢? 0.5
1 / 2 联 想 到 二 进 制 位 1/2联想到二进制位 1/2
1 / 2 = 0.1 1/2=0.1 1/2=0.1
1 / 2 = 0.01 1/2=0.01 1/2=0.01
1 / 4 = 0.001 1/4=0.001 1/4=0.001
. . . ... ...
如 果 可 以 直 接 用 已 有 的 串 构 造 0.1 , 那 自 然 就 直 接 构 造 。 如果可以直接用已有的串构造0.1,那自然就直接构造。 0.1
否 则 , 就 需 要 用 2 个 0.01 构 造 。 否则,就需要用2个0.01构造。 20.01
这 一 看 不 就 是 简 单 的 搜 索 吗 ? 这一看不就是简单的搜索吗?
d f s ( x , c n t ) 表 示 构 造 c n t 个 x 是 否 可 行 ? 初 始 状 态 为 d f s ( 0.1 , 1 ) 目 的 是 贪 心 , 这 样 构 造 出 的 串 就 最 接 近 0.5 dfs(x,cnt)表示构造cnt个x是否可行?初始状态为dfs(0.1,1)\\目的是贪心,这样构造出的串就最接近0.5 dfs(x,cnt)cntxdfs(0.1,1)0.5
这 题 复 杂 度 分 析 一 下 。 这题复杂度分析一下。
由 于 我 没 有 离 散 化 , 值 与 数 量 的 映 射 是 用 m a p 建 立 由于我没有离散化,值与数量的映射是用map建立 map
d f s 状 态 递 归 层 数 为 m i n ( n , m ) 其 中 2 m < = n dfs状态递归层数为min(n, m)其中2^m<=n dfsmin(n,m)2m<=n
因 此 复 杂 度 为 O ( n + n l o g n ) 因此复杂度为O(n+nlogn) O(n+nlogn)

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const ll inf = 1e18;
const int maxn = 7e5 + 10;

map<int, int> mp;
map<int, stack<int>> res;
int n, kase;
int flag[maxn], ma;
bool dfs(int val, int cnt, int o){
	if(val > ma || cnt > n) return false;
	int num = mp[val]; stack<int> stk = res[val];
	if(num >= cnt){
		mp[val] = num - cnt;
		for(int i = 1; i <= cnt; i++) flag[stk.top()] = o, stk.pop();
		res[val] = stk;
		return true;
	}
	else{
		int gg = cnt - num;
		mp[val] = 0;
		for(int i = 1; i <= num; i++) flag[stk.top()] = o, stk.pop();
		res[val] = stk;
		return dfs(val + 1, 2 * gg, o);
	}
}
int main(){
	int t; kase = 0;
	scanf("%d", &t);
	while(t--){
		kase++;
		mp.clear(); res.clear();
		scanf("%d", &n); ma = 0;
		for(int i = 1; i <= n; i++) flag[i] = 1;
		int k;
		for(int i = 1; i <= n; i++){
			scanf("%d", &k); mp[k]++; res[k].push(i); ma = max(ma, k);
		}
		bool ok = false;
		if(dfs(1, 1, 0) && dfs(1, 1, 1)){
			ok = true;
		}
		if(ok){
			printf("Case %d: YES\n", kase);
			for(int i = 1; i <= n; i++){
				printf("%d", flag[i]);
			}
			putchar('\n');
		}
		else{
			printf("Case %d: NO\n", kase);
		}
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值