感受
有
点
简
单
,
一
开
始
还
担
心
精
度
问
题
,
后
来
想
了
想
与
精
度
无
关
有点简单,一开始还担心精度问题,后来想了想与精度无关
有点简单,一开始还担心精度问题,后来想了想与精度无关
思路
考
虑
如
何
利
用
已
知
串
构
造
一
个
最
接
近
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构造。
否则,就需要用2个0.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)表示构造cnt个x是否可行?初始状态为dfs(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
dfs状态递归层数为min(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;
}