[gcjkickstart2018roundb] b. sherlock and the bit strings

https://code.google.com/codejam/contest/10284486/dashboard#s=p1

给一个长为n的01串,现在规定在串的一些区间$[A_i,B_i]$中至少存在$C_i$个1,求满足条件的字典序为第$p$大的串。

小数据可以直接暴力,记下空位和$p$的二进制形式,然后从低到高扫01串就可以。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

using namespace std;

using LL = long long;
const int maxn = 110;
int n, k;
LL p;
int a[maxn], b[maxn], c[maxn];
vector<int> pos;
string ret;

signed () {
freopen("in", "r", stdin);
freopen("out", "w", stdout);
int T, _ = 1;
scanf("%d", &T);
while(T--) {
scanf("%d%d%lld" ,&n,&k,&p);
p--;
pos.clear();
ret.resize(n); fill(ret.begin(), ret.end(), '#');
for(int i = 0; i < k; i++) {
scanf("%d%d%d",&a[i],&b[i],&c[i]);
if(c[i]) ret[a[i]-1] = '1';
else ret[a[i]-1] = '0';
}
while(p) {
pos.emplace_back(p&1);
p >>= 1;
}
int j = n - 1;
for(int i = 0; i < pos.size(); i++) {
if(pos[i] == 1) {
while(ret[j] == '1' || ret[j] == '0') j--;
ret[j--] = '1';
}
else if(pos[i] == 0) {
while(ret[j] == '1' || ret[j] == '0') j--;
ret[j--] = '0';
}
}
for(int i = 0; i < ret.length(); i++) {
if(ret[i] == '#') ret[i] = '0';
}
cout << "Case #" << _++ << ": " << ret << endl;
}
return 0;
}